;;; Copyright (c) 1999 Massachusetts Institute of Technology
;;;
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License as
;;; published by the Free Software Foundation; either version 3 of the
;;; License, or (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, see https://gnu.org/licenses or
;;; write to:
;;;  Free Software Foundatiom, Inc.
;;;  51 Franklin St, Fifth Floor
;;;  Boston, MA 02110-1301
;;;  USA

SUBTTL	ARPANET NCP variables and tables

EBLK
IMPMQS==13.	;MESSAGE QUEUE SIZE (LENGTH WORD, 6-WORD LEADER, 6-WORD TEXT)
;MAIN PROGRAM CONTROL MESSAGE VARIABLES
IMPMPU:	-1	;-1 => FREE
	0	;SWTL THREAD
IMPMPL:	-1	;LINK WORD FOR CONTROL LINK QUEUE
IMPMPC:	BLOCK IMPMQS	;FIRST WORD HAS IMPHTB INDEX,,LENGTH OF TEXT

;PI CONTROL MESSAGE VARIABLES
IMNPIC==NNETCH+3	;NUMBER OF BLOCKS IN PI CONTROL QUEUE
;HOPEFULLY THIS IS ENOUGH.  THE CODE RESPONDS VERY UNGRACEFULLY TO THIS
;QUEUE FILLING UP.  IN PARTICULAR, WHEN IT HOLDS UP INPUT IT CAN CAUSE
;A DEADLOCK BY PREVENTING ITSELF FROM SEEING A CONTROL-LINK RFNM IT
;NEEDS IN ORDER TO SEND SOMETHING THAT'S IN THE QUEUE AND FREE UP SOME
;SPACE.  FURTHERMORE THE IMP IS UNGRACEFUL AND WILL SOMETIMES REFUSE TO
;READ INPUT FROM US (EVEN IN THE MIDDLE OF A MESSAGE) UNTIL WE READ
;INPUT FROM IT.  BUT WE DO THE SAME THING WHEN THIS QUEUE FILLS UP.
;FURTHERMORE SOMETIMES THE CORE JOB WILL WAIT FOR A NETWORK
;TRANSMISSION TO COMPLETE SO IT CAN MOVE A NETWORK BUFFER, HANGING THE
;ENTIRE SYSTEM.  THE CORE-JOB WILL UNHANG AFTER THE IMP TIMES OUT AND
;FLASHES ITS READY LINE (SEE IMPBER).
;** BUT SOMETIMES THE IMP NEVER TIMES OUT AND SO THE SYSTEM IS HUNG **

IMPCQ:	REPEAT IMNPIC-1,[
	.+IMPMQS+1	;POINTER TO NEXT FREE OR NEXT IN QUEUE
	BLOCK IMPMQS	;FIRST WORD HAS IMPHTB INDEX,,LENGTH OF TEXT
]
	-1
	BLOCK IMPMQS
IMPNCQ:	-1	;NEXT ENTRY TO BE SENT.  -1 IF NONE
IMPLCQ:	-1	;POINTER TO LAST ENTRY IN CONTROL QUEUE
IMFFCQ:	IMPCQ	;POINTER TO FIRST FREE.  -1 IF NONE
IMFCQL:	IMNPIC	;NUMBER FREE CONTROL QUEUE ENTRIES LEFT

;PENDING RFC QUEUE
IMNPQ==20	;NUMBER OF PENDING QUEUE ENTRIES
;(0)	POINTER TO NEXT IN CHAIN OR NEXT FREE.  -1 IF NONE
;(1)	LOCAL SOCKET NUMBER
;(2)	FOREIGN SOCKET NUMBER
;(3)	4.9 = 1 => RTS  = 0 => STR
;	1.1-1.8 = LINK NUMBER OR BYTE SIZE
;	1.9-2.7 = FOREIGN HOST NUMBER
;	3.1-3.9 = TIME RFC RECEIVED, IN SECONDS MOD 512.
	IMPPQ		;IMPBPQ-1 IS BEGINNING OF GETSYS BLOCK, THIS WORD FOR UNRELOCATION
IMPBPQ:	-1	;BEGINNING OF PENDING QUEUE.  -1 IF EMPTY
IMPPQ:	REPEAT IMNPQ-1,[
	.+4
	BLOCK 3
]
	-1
	BLOCK 3
IMPEPQ:	-1	;END OF PENDING QUEUE.  -1 IF EMPTY (IMPEPQ IS END FOR GETSYS BLOCK)
IMFFPQ:	IMPPQ	;FIRST FREE PENDING QUEUE ENTRY.  -1 IF NONE

;SOCKET TABLE

IMSOKB:	IMPSTL		;BEGIN OF GETSYS BLOCK, LENGTH STORED HERE

IMSOC1:	REPEAT IMPSTL,0		;0 => FREE
				;>0 MEANS ALLOCATED, NOT SET UP YET
				;4.9 = 1 => SOCKET IN USE
				;4.8 = 1 => CHNL TRYING TO BE CLOSED
				;3.1-4.7 = MASK FOR CHANNEL SOCKET IS OPEN ON.
				;RH = USER INDEX

IMSOC2:	BLOCK IMPSTL		;1.1-4.5 = LOCAL SOCKET NUMBER
				;4.6-4.9  0 (MAKES COMPARISONS EASIER)
IMSOC3:	BLOCK IMPSTL		;1.1-4.5 = FOREIGN SOCKET NUMBER
				;4.6-4.9 = 0
IMSOC4:	BLOCK IMPSTL		;3.1-3.8 = LINK NUMBER
				;3.9-4.7 = FOREIGN HOST NUMBER (IMPHTB INDEX)
				;	   377 MEANS NOT USING ANY HOST
				;4.8 = SET BY RCV CLS - MAKES MATCH USING IMSCHD FAIL
				;4.9 = SEND THIS BUFFER NOW
	.SEE %NS		;RH = SOCKET STATE
IMSOC5:	BLOCK IMPSTL		;1.1 - 1.9 => TTY # OF STY, IF CONNECTED TO ONE.
				;2.1-2.9 = CLOSE-REASON
				;3.1-3.8 = CONNECTION BYTE SIZE
				;3.9 => ASCII MODE - 7 BIT
				;4.1 => ASCII MODE - 8 BIT
				;4.2 => 1 BIT BYTES
				;4.3 => NET INT (INR\INS) RECEIVED
				;4.4 => HAVE BEGUN COUNTING THE CLOSE TIME-OUT.
				;4.5 => CLOSED WHILE IN RFNM WAIT, EXPECT ANOTHER RFNM
				;4.6 => CONNECTED DIRECTLY TO A STY.
				;4.7 => DON'T BUFFER MORE OUTPUT THAN ALLOCATION
				;4.8 => STY WANTS WAKEUP AT 1/2 SEC CLK
				;4.9 => TRANSFER IN 32 BIT MODE
IMSOC6:	BLOCK IMPSTL		;RH => BUFFER ADDRESS
				;4.9 => LOCKED BY CORE JOB
				;4.8 => ACTIVE AT PI LEVEL
				;4.7 => INPUT OCCURRED WHILE BUFFER LOCKED
				;3.1-3.8 => IOBFT INDEX (377 IF USING BIG BUFFER)
IMSOC7:	BLOCK IMPSTL		;BIT ALLOCATION
IMSOC8:	BLOCK IMPSTL		;MESSAGE ALLOCATION
IMSC7I:	BLOCK IMPSTL		;AMT TO INCREASE BIT ALLOCATION BY IN NEXT ALLOC MSG (INPUT)
				;FOR OUTPUT, HAS NUMBER OF BITS IN BUFFER
IMSC8I:	BLOCK IMPSTL		;AMT TO INCREASE MESSAGE ALLOCATION BY NEXT ALLOC MSG (INPUT)
IMSOCT:	BLOCK IMPSTL		;TIME WHEN FIRST MESS PUT INTO BUF
				;(DURING INPUT HAS NUMBER OF DATA BYTES LEFT IN CUR MSG)
				;(DURING CLOSE HAS TIME TIME-OUT STARTED)
IMSMPP:	BLOCK IMPSTL		;MAIN PROGRAM POINTER, ILDB OR IDPB FOR NEXT BYTE
IMSMPC:	BLOCK IMPSTL		;MAIN PROGRAM COUNTER, FOR OUTPUT HAS NUMBER OF DATA
				; BYTES OF ROOM LEFT IN BUFFER.  FOR INPUT HAS TOTAL
				; NUMBER OF DATA BYTES IN BUFFER.
IMSPIP:	BLOCK IMPSTL		;INTERRUPT LEVEL POINTER, FOR OUTPUT ILDB TO GET NEXT
				; BYTE OUT AT P.I. LEVEL.  FOR INPUT POINTS TO WHERE
				; HEADER WORD OF NEXT MESSAGE IN WILL BE STORED.
IMSBFE:	BLOCK IMPSTL		;BYTE POINTER TO LAST BYTE IN BUFFER
				;USE CAILE X,@IMSBFE(I) TO CHECK A WORD ADDRESS
IMSOKE==.-1		;END OF BLOCK FOR GETSYS CALL

BBLK

IMSCLN:	221000,,IMSOC4(I)	;LINK NUMBER
IMSCBS:	221000,,IMSOC5(I)	;BYTE SIZE
IMSCLS:	111100,,IMSOC5(I)	;CLOSE REASON
IMSCFH:	321000,,IMSOC4(I)	;FOREIGN HOST
IMSCHD:	222100,,IMSOC4(I)	;FOREIGN HOST AND LINK NUMBER
				; EXTRA BIT, SET WHEN RCV CLS
IMSCHL:	222000,,IMSOC4(I)	;FOREIGN HOST AND LINK WITHOUT EXTRA BIT

NTRFCL:	SIXBIT /NETRFC/		;FOR ICP ON ANY SOCKET < 1000
EBLK
	0

NETSRS==1000	;SMALLEST USER RECEIVE SOCKET NUMBER
NRSOC:	NETSRS	;NUMBER OF NEXT RECEIVE SOCKET TO BE GENERATED
NETOSW:	-1	;SWITCH LOCKED AT NET OPEN
	0
NETHSW:	-1	;SWITCH LOCKED IF HACKING HOST TABLE (IMPHTB)
	0
NETLST:	0	;LIST OF USERS IN NETWORK OPEN CODE

;INPUT BUFFER FORMAT:
;THE BUFFER IS CIRCULAR, AND EITHER 200 OR 2000 WORDS LONG.
;MAY CONTAIN SEVERAL MESSAGES.  EACH CONSISTS OF A HEADER WORD CONTAINING
; THE NUMBER OF BYTES IN THE MESSAGE, FOLLOWED BY THE BYTES, FOLLOWED BY
; UNUSED BITS UP TO THE NEXT WORD BOUNDARY.  THIS WEIRD FORMAT IS USED
; TO AVOID HAVING TO DO BYTE OPERATIONS AT P.I. LEVEL.
;A HEADER WORD OF -1 MEANS THAT THAT MESSAGE HAS NOT YET BEEN STORED.
;IMSPIP(I) ALWAYS CONTAINS THE ADDRESS OF A HEADER WORD OF -1.
;IMSMPP(I) HAS A BYTE POINTER TO THE NEXT DATA BYTE TO BE READ.
;P.I. LEVEL CAN STORE A MESSAGE INTO THE PART OF THE BUFFER FROM
;@IMSPIP TO @IMSMPP-1.
;IMSOCT(I) HAS THE NUMBER OF BYTES THAT MAIN PROGRAM LEVEL CAN
; READ BEFORE IT GETS TO THE END OF THE CURRENT MESSAGE AND HAS
; TO CHECK THE NEXT HEADER.
;IMSMPC(I) HAS THE TOTAL NUMBER OF DATA BYTES IN ALL THE MESSAGES
; IN THE BUFFER.

;OUTPUT BUFFER FORMAT:
;THE BUFFER IS CIRCULAR, AND EITHER 200 OR 2000 WORDS LONG.
;IT SIMPLY CONTAINS A STRING OF BYTES.
;IMSMPP(I) HAS A BYTE POINTER TO WHERE THE NEXT BYTE TO BE OUTPUT WILL BE DEPOSITED.
;IMSPIP(I) HAS A BYTE POINTER TO WHERE THE NEXT BYTE TO BE SENT OUT AT P.I.
; LEVEL WILL COME FROM.  P.I. LEVEL TRIES TO KEEP EVERYTHING ALIGNED ON
; WORD BOUNDARIES SO THAT IT DOESN'T HAVE TO DO BYTE OPERATIONS.
;IMSMPC(I) HAS THE NUMBER OF BYTES THAT MP LEVEL MAY STORE BEFORE RUNNING
; INTO OLD BYTES THAT HAVEN'T YET BEEN TRANSMITTED.
;IMSOCT(I) IS SET TO THE TIME THE FIRST BYTE IS PUT INTO THE BUFFER.
; IT IS CLEARED WHENEVER THE BUFFER GETS EMPTIED.

BBLK

SUBTTL	ARPANET NCP Main Prog system call routines

;NET .CALL RCHST/RFNAME
NETRCH:	MOVEI W,8		;WE RETURN 8 VALUES.
	HRRE I,A
	JUMPL I,NETRC3		;NET WENT DOWN AFTER THIS CHANNEL WAS OPENED.
	MOVE B,IMSOC2(I)	;LOCAL SOCKET NUMBER
	MOVE C,IMSOC3(I)	;FOREIGN SOCKET NUMBER
	LDB TT,IMSCFH		;FOREIGN HOST FOR 4TH WORD.
	CAIN TT,377
	 TDZA D,D		; 377 MEANS NOT USING ANY HOST
IFN 1,[
	  JRST [MOVE D,A
		MOVE A,IMPHTN(TT)	; Get host addr
		TLO A,(NW%ARP)		; Make full HOSTS3 format
		CALL CVH2NA		; Convert to HOSTS2 for compatibility
		EXCH A,D
		JRST .+1]
] ;IFN 1
IFN 0,[
	 TDZA Q,Q
	  MOVE Q,IMPHTN(TT)
	LDB D,[112000,,Q]	;TRANSLATE NEW HOST NUMBER TO OLD
	ANDI Q,377		;IF IT WILL FIT IN OLD NOTATION
	CAIGE D,100
	 CAIL Q,4
	  SKIPA D,IMPHTN(TT)
	   DPB Q,[060200,,D]
] ;IFN 0

	LDB Q,IMSCBS		;GET BYTE SIZE FOR HERE AND BELOW
;FOLLOWING LINE HAS BEEN PUNTED, AN INCOMPATIBLE CHANGE
;	DPB Q,[111100,,D]	;INTO 2.9-2.1 OF 4TH WORD
	MOVE A,IMSOC5(I)	;RANDOM WORD
	TLNE A,4000		;SKIP IF 4.3 BIT OFF (NETWRK INT)
	 TLO D,400000		;SET FOR USER
	PUSHJ P,NETRC1		;GET TIME IMP GOING DOWN,
	HRR TT,IMSOC4(I)	;MERGE IN SOCKET STATE.
	IMUL Q,IMSMPC(I)	;MULTIPLY BYTE SIZE BY BYTES AVAIL TO GET BITS AVAIL
	LDB I,IMSCLS		;CLS REASON
	POPJ P,

NETRC3:	MOVEI I,%NCNCP		;GIVE CLOSE REASON THAT OUR NCP WENT DOWN.
NETRC1:	SKIPG TT,IMPDWN+1	;SYS TIME AT WHICH IMP IS GOING DOWN
	 JRST NETRC2
	SUB TT,TIME		;(TIME TIL IMP DOWN -1=NOT. 0=DOWN, +=GOING DOWN, N/30. SEC)
	SKIPG TT
	 MOVEI TT,1		;IF SET TO GO DOWN, AND TIME "PASSED", SAY SOON IF NOT ALREADY DOWN
NETRC2:	HRLZS TT
	POPJ P,

;NET .CALL STATUS - SOCKET STATE IN BITS 2.4-2.9
STANET:	TRNN A,400000		;SKIP IF NET WENT DOWN ON THIS LOSER
	 SKIPA E,IMSOC4(A)	;GET STATE
	  MOVEI E,0		;IF NCP WENT DOWN, STATE IS "CLOSED"
	DPB E,[140600,,D]
	POPJ P,

;NET .CALL RESET - ONLY RESETS "INT FM NETWORK" BIT (INR/INS)
NETRS:	HLRZ A,(R)		;GET LH IOCHNM
	MOVSI B,4000		;4.3 BIT
	TRNN A,400000		;SKIP IF SET TO -1 (NET WENT DOWN ON THIS CHAN)
	 ANDCAM B,IMSOC5(A)	;CLEAR BIT
	POPJ P,

;NET .CALL IOPUSH/IOPOP - ALTER THE CHANNEL-OPEN MASK IN IMSOC1.
NETIOP:	HRRZ T,UUAC(U)
	IMUL I,CHNBIT(T)	;PUSHING => 0; ELSE BIT FOR CHANNEL BEING POPPED.
	HLRZ T,(R)		;GET SOCKET TABLE IDX
	TRNN T,400000		;SKIP IF NET WENT DOWN ON THIS LOSER
	 DPB I,[222000,,IMSOC1(T)] ;STORE MASK AWAY.
	POPJ P,

;NET .CALL WHYINT
;RESULTS ARE %WYNET, SOCKET STATE, BYTES AVAIL, CLS REASON
NETWHY:	HRRE I,A		;GET IMSOC INDEX
	MOVEI A,%WYNET		;FIRST RESULT IS DEVICE CODE
	SETZB B,C		;SET UP RESULTS 2-4 IN CASE NCP WENT DOWN
	MOVEI D,%NCNCP
	JUMPL I,POPJ1		;RETURN IF NCP WENT DOWN ON THIS LOSER
	HRRZ B,IMSOC4(I)	;SECOND RESULT IS SOCKET STATE
	MOVE Q,IMSOC5(I)
	TLNE Q,4000
	 TLO B,400000		;SIGN OF SECOND RESULT SET IF NETWRK INT
	TLNE Q,40000		;DIRECT CONNECTED?
	 TDZA C,C		;YES, NO BYTES AVAILABLE FOR INPUT
	  MOVE C,IMSMPC(I)	;THIRD RESULT IS BYTES AVAILABLE
	LDB D,IMSCLS		;FOURTH RESULT IS CLOSE REASON
	JRST POPJ1

;AIDS TO NETWORK OPEN AND NETHST CALLS

;SET THINGS UP AND ALLOCATE AN IMSOC INDEX.
;SKIP RETURNS WITH NETLST AND IMSOC1(I) LOCKED.
;OR, RETURNS NO-SKIP WITH NOTHING LOCKED AND AN ERROR SIGNALLED.
NETO00:	PUSHJ P,LSTSET	;ADD THIS JOB TO LIST OF NET OPENERS
	    NETLST
	PUSHJ P,SWTL	;GET AN IMSOC ENTRY TO GC-PROTECT OUR IMPHTB ENTRY
	    NETOSW
	MOVSI I,-IMPSTL
	SKIPE IMSOC1(I)
	 AOBJN I,.-1
	JUMPG I,OPNL6	;DEVICE FULL
	MOVEI H,377	;NO HOST YET
	DPB H,IMSCFH
	HRRZM U,IMSOC1(I) ;IMSOC1 POSITIVE MEANS ALLOCATED BUT NOT INITED YET
	PUSHJ P,LSWPOP	;NETOSW
	PUSHJ P,LOSSET	;RETURN IMSOC ENTRY IF PCLSR
	    NETIRT
	JRST POPJ1

;LOSSET ROUTINE TO RETURN IMSOC ENTRY
NETIRT:	MOVE T,AC0S+I(U)
	HRRZ A,U
	CAME A,IMSOC1(T)
	 JRST 4,.
	SETZM IMSOC1(T)
	POPJ P,
	
;SUBROUTINE TO OPEN UP COMMUNICATIONS WITH THE DESIRED HOST.
;ENTER WITH HOST NUMBER IN SRN3(U), SKIP-RETURN WITH HOST
;UP AND IMPHTB INDEX IN H AND IMSCFH.  OR NON-SKIP RETURN WITH ERROR SIGNALLED.
NETOR:	MOVE T,SRN3(U)	;USER-SPECIFIED HOST NUMBER
	JSP J,STDHST	;STANDARDIZE, OPNL25 IF IT IS NO GOOD
	CONO PI,NETOFF
	PUSHJ P,FNDHST	;H GETS HOST TABLE INDEX
	 JRST OPNL6	;DEVICE FULL (HOST TABLE FULL)
	DPB H,IMSCFH	;PROTECT IN IMSOC4
	CONO PI,NETON
	PUSHJ P,SWTL	;POSSIBLY SEND RST TO HOST OPENING CONNECTION TO
	    NETHSW
	LDB J,IMHSBT	;GET STATUS
	SOJG J,NETORS	;-1 => DOWN, 0 => RST SENT, 1 => UP
	JUMPE J,NETOR1	;WAIT FOR REPLY
	PUSHJ P,NETOW	;WAIT FOR IMPMPC TO BE FREE
	LDB W,[051100,,TIME]
	DPB W,[221100,,IMPHTB(H)]
	MOVEI J,1
	DPB J,IMHSBT	;MARK AS SENT
	AOS IMRFCT
	PUSHJ P,STHSTM	;STORE HOST#, LINK 0 , MESSAGE TYPE 0
	MOVE W,[8_24.+1_8]	;BYTE SIZE = 8, BYTE COUNT = 1
	MOVEM W,IMPMPC+6
	MOVE W,[12._28.]	;RST
	MOVEM W,IMPMPC+7
	MOVEI W,1
	HRRM W,IMPMPC	;MESSAGE LENGTH
	PUSHJ P,IMPMPQ	;SEND IT OUT
NETOR1:	PUSHJ P,LSWPOP	;NETHSW
	PCLT
	MOVSI T,1000
	TDNE T,IMPHTB(H) ;RRP -> 2000,  DOWN -> 0000
	 PUSHJ P,UFLS
	LDB J,IMHSBT	;GET STATUS
	SOJL J,OPNL41	;HOST DOWN
	JUMPE J,NETOR	;TRY ALL THIS AGAIN
	JRST POPJ1	;HOST UP

NETORS:	PUSHJ P,LSWPOP	;NETHSW
	JRST POPJ1	;HOST IS UP

;NETWORK OPEN

;	.OPEN CH,BLK
;	ERROR RETURN
;	NORMAL RETURN

;BLK:	MODE BITS,,(SIXBIT /NET/)
;	LOCAL SOCKET NUMBER (1.1-4.5)
;	FOREIGN SOCKET NUMBER (1.1-4.5)
;	FOREIGN HOST NUMBER

;BLK:	3.1-3.3 => STANDARD ASCII/IMAGE, UNIT/BLOCK, INPUT/OUTPUT
;	3.4 = 1 => GENERATE UNIQUE LOCAL RECEIVE (SEND) SOCKET NUMBER
;	3.4 = 0 => USE LOCAL SOCKET NUMBER SPECIFIED IN BLK+1
;	3.5 => OPEN SOCKET IN LISTEN MODE
;	3.6 => IF IMAGE MODE, USE BYTE SIZE IN 4.1-4.6
;	       IF ASCII MODE, USE 8 BIT BYTES RATHER THAN 7
;	3.7 => USE BIG BUFFER (2000 WORDS INSTEAD OF 200)
;	3.8 => DON'T BUFFER MORE OUTPUT THAN ALLOCATION
;	4.1-4.6 = BYTE SIZE IN IMAGE MODE


;OPEN CODE
NETO:	SKIPN IMPUP
	 JRST NETOUP
	SKIPL IMPUP
	 JRST OPNL7	;DEVICE NOT READY
	CONO PI,NETOFF
	SKIPN IMPTCU
	 AOS IMPTCU
	CONO PI,NETON
	MOVSI I,SCLIMP
	IORM I,SUPCOR	;HAVE SYS JOB BRING UP THE NETWORK
	PCLT
	SKIPE IMPTCU	;WAIT WHILE IT TRIES TO COME UP
	 PUSHJ P,UFLS
	SKIPE IMPUP
	 JRST OPNL7	;LOSE IF NOT UP BY NOW
NETOUP:	TLZ A,740000	;IGNORE EXTRA BITS IN SOCKET NUMBERS
	TLZ B,740000
	PUSHJ P,NETO00	;INITIALIZE THINGS
	 POPJ P,	;NETWORK NOT UP OR FULL
	TLNE C,20	;SKIP IF NOT LISTEN
	 JRST NETO10
	PUSHJ P,NETOR	;DO RESET STUFF, OPEN COMMUNICATIONS WITH HOST
	 POPJ P,	;HOST DOWN OR ILLEGAL
	MOVE J,B	;CHECK GENDER OF FOREIGN SOCKET
	ROT J,-1
	XOR J,D
	JUMPGE J,OPNL2	;WRONG DIRECTION
;DROPS THROUGH
;DROPS IN
NETO10:	PUSHJ P,SWTL	;ONLY ONE PROCESS AT A TIME COMPARING SOCKET NUMBERS
	    NETOSW
	TLNN C,20	;SKIP IF LISTEN
	 PUSHJ P,NETOW	;GOBBLE MP CONTROL LINK BLOCK (FOR NETOS)
	TLNN C,10
	 JRST NETO1	;USE SOCKET NUMBER GIVEN IN WORD 2
	MOVEI A,10	;ADVANCE SYSTEM UNIQUE SOCKET NUMBER
	ADDB A,NRSOC
	SUBI A,10	;UNIQUE RECEIVE SOCKET NUMBER
	SKIPGE D	;SKIP IF OPEN IS FOR READ (RECEIVE)
	 IORI A,1	;MAKE INTO SEND SOCKET
	JRST NETO6

NETO1:	MOVE J,A	;USER SPECIFIED SOCKET NUMBER
	ROT J,-1	;J 4.9: 0 => RECEIVE  1 => SEND
	EQV J,D		;D 4.9: 0 => READ  1 => WRITE
	JUMPGE J,OPNL2	;WRONG DIRECTION
	MOVE J,A
	CAIL A,NETSRS	;SKIP IF SPECIAL SOCKET
	 TRZA J,7	;J HAS BASE OF SOCKET GROUP
	  MOVNI J,1	; OR -1 IF NOT IN A GROUP
	MOVSI Q,-IMPSTL
	MOVEI E,0
NETO2:	SKIPL W,IMSOC1(Q)
	 JRST NETO3	;NOT HOOKED UP
	CAMN A,IMSOC2(Q)
	 JRST NETO2A	;DUPLICATE LOCAL SOC #
	MOVE T,IMSOC2(Q)
	TRZ T,7
	CAMN J,T
	 JRST NETO4	;JUMP IF PART OF SOCKET GROUP
NETO3:	AOBJN Q,NETO2
	SKIPL J		;SKIP IF NOT PART OF A SOCKET GROUP
	 JUMPE E,OPNL23	;FOUND NO EVIDENCE THAT THIS GUY OWNS THIS GROUP
	JRST NETO6	;WINNING

NETO2A:	TLNN W,200000	;SKIP IF BEING CLOSED
	 JRST OPNL13	;NO, GIVE ERROR
	TLNN C,20
	 PUSHJ P,LSWPOP	;POP MP CONTROL LINK BLOCK
	PUSHJ P,LSWPOP	;NETOSW
	MOVSI T,200000
	PCLT
	TDNE T,IMSOC1(Q)
	 PUSHJ P,UFLS	;WAIT TILL CLOSED
	JRST NETO10	;TRY AGAIN

NETO4:	CAIE U,(W)
	 JRST OPNL23	;SOMEONE ELSE HAS IT
	MOVNI E,1	;OK IF NO OTHER CONFLICTS
	JRST NETO3

;HERE WITH SUITABLE LOCAL SOCKET IN A
NETO6:	TLNN C,4	;SKIP IF IMAGE MODE
	 JRST NETOC	;ASCII MODE
	MOVEI TT,36.
	TLNN C,40	;SKIP IF BYTE SIZE SUPPLIED
	 JRST NETOB
	LDB E,[330600,,C]	;USE USER SUPPLIED BYTE SIZE
	IDIVI E,36.	;TT GETS BYTE SIZE MOD 36.
	JUMPN TT,NETOB
	MOVEI TT,36.	;36 BITS ANYWAY
NETOB:	PUSH P,TT
	MOVEI E,36.
	IDIV E,TT	;36/BS
	JUMPE TT,NETOB1	;EXACT
	MOVEI E,32.
	IDIV E,(P)	;32/BS
	JUMPE TT,[MOVEI TT,400000	;32BIT MODE FLAG
		 JRST NETOB1]
	MOVEI TT,2000		;FUNNY BYTESIZE FLAG
NETOB1:	POP P,E		;BS
	ADD TT,E	;FLAGS+BS
	JRST NETOA

NETOC:	MOVEI TT,400410		;7 BIT
	TLNE C,40
	 MOVEI TT,401010	;8 BIT
NETOA:	TLNE C,200
	 TRO TT,100000		;DON'T BUFFER MORE OUTPUT THAN ALLOCATION
	HRLZM TT,IMSOC5(I)	;STORE FLAGS AND BC, CLEAR CLOSE REASON
	MOVEM A,IMSOC2(I)	;LOCAL SOCKET NUMBER
	MOVEM B,IMSOC3(I)	;FOREIGN SOCKET NUMBER
	SETZM IMSOCT(I)		;IF INPUT, NOT IN MIDDLE OF A MESSAGE
	MOVEI W,%NSRFS
	TLNE C,20		;3.5 LISTEN
	 MOVEI W,%NSLSN
	DPB H,[321000,,W]	;DON'T CHANGE HOST NUMBER FIELD OF IMSOC4
	MOVEM W,IMSOC4(I)	;SET INITIAL STATE, CLEAR FLAGS
	SKIPE IMSOC6(I)		;SKIP IF HAVEN'T ASSIGNED BUFFER YET
	 JRST 4,.
	PUSH P,A
	PUSH P,B
	PUSH P,D
NETOE1:	TLNN C,100		;LAST PLACE TO PCLSR (REALLY NETMW)
	 JRST NETOE7
	PUSHJ P,TCALL		;GET FULL-PAGE BUFFER
	    JRST IOMQ
	 JRST NETMW
	MOVEI W,MUNET
	DPB W,[MUR,,MEMBLT(A)]
	DPB I,[MNUMB,,MEMBLT(A)]
	LSH A,10.
	MOVE W,A		;BUFFER START ADDRESS
	HRLI W,377		;NOT AN IOBFT-TYPE BUFFER
	MOVEI A,1777(A)		;BUFFER END ADDRESS
	JRST NETOE4

NETOE7:	MOVEI D,NFNETC(I)
	PUSHJ P,TCALL
	    JRST IUTCO1		;GET 200-WD BUFFER
	 JRST NETMW		;NO MEM AVAIL
	LDB W,[IOSA,,IOBFT(A)]
	LSH W,6			;STARTING ADDRESS
	HRL W,A			;IOBFT INDEX
	MOVEI A,177(W)		;BUFFER END ADDRESS
NETOE4:	MOVEM A,IMSBFE(I)	;(LH WILL BE STORED LATER)
	MOVEM W,IMSOC6(I)
;CLEAR THE BUFFER FOR EASE IN DEBUGGING.  COMMENT USED TO CLAIM
;THAT CLEARING IT WAS NECESSARY IN ORDER TO OUTPUT CORRECT HEADERS,
;BUT THAT WAS FRAUDULENT SINCE HEADERS NEVER COME FROM THE BUFFER.
	MOVEI D,1(W)
	HRLI D,(W)
	SETZM (W)
	BLT D,(A)
	POP P,D
	POP P,B
	POP P,A
;DROPS THROUGH
;DROPS IN

	MOVSI Q,000100		;SET UP THE VARIOUS BYTE POINTERS
	LDB TT,IMSCBS		;TO POINT TO END OF BUFFER
	MOVE E,IMSOC5(I)	;SO ILDB WILL GET FIRST BYTE IN BUFFER
	TLNN E,2000		;SKIP IF ONE BIT BYTES
	 DPB TT,[300600,,Q]	;OTHERWISE USE USER BYTE SIZE
	SKIPGE E
	 TLO Q,040000		;32 BIT WORD ENDS 4 BITS OVER
	HRR Q,IMSBFE(I)
	MOVEM Q,IMSMPP(I)
	MOVEM Q,IMSPIP(I)
	MOVEM Q,IMSBFE(I)
	MOVE T,C		;GET 3.5 BIT OF C INTO
	LSH T,13.		;4.9 OF T
	JUMPL D,NETOE5		;JUMP IF SENDER
	SETOM (W)		;NULL FIRST HEADER WORD
	TLO Q,440000		;-> LEFT END OF WORD
	HRR Q,W
	MOVEM Q,IMSPIP(I)	;SET PI PNTR TO POINT TO FIRST MESSAGE HEADER
	SETZM IMSMPC(I)		;NO INPUT BYTES AVAILABLE YET
	MOVEI TT,20.		;MESSAGE ALLOCATION ALWAYS 20
	MOVEM TT,IMSOC8(I)
	HRRZ TT,IMSBFE(I)	;COMPUTE BIT ALLOCATION
	SUBI TT,2*20.(W)	;TT := # WORDS IN BUFFER, -1 FOR LUCK, -2 FOR EACH MSG
	SKIPGE IMSOC5(I)	; (-1 FOR HEADER WORD, AND -1 FOR BREAKAGE)
	 IMULI TT,32.		;CONVERT TO # BITS
	SKIPL IMSOC5(I)
	 IMULI TT,36.
	LDB Q,IMSCBS		;BREAKAGE WAS OVER-ESTIMATED BY 1 BYTE PER MSG
	IMULI Q,20.
	ADD TT,Q
	MOVEM TT,IMSOC7(I)	;STORE CORRECT BIT ALLOCATION
	SETZM IMSC8I(I)
	SETZM IMSC7I(I)
	MOVEI Q,2(I)		;LINK #
	DPB Q,IMSCLN		;STORE IN LINK # FIELD
	JRST NETOE6

NETOE5:	SETZM IMSOC7(I)		;INITIALIZE SENDER'S ALLOCATIONS
	SETZM IMSC7I(I)
	SETZM IMSOC8(I)
	HRRZ TT,IMSBFE(I)
	SUBI TT,(W)		;# BUFFER WORDS, -1 FOR LUCK
	SKIPGE IMSOC5(I)	;SKIP IF 36BIT
	 IMULI TT,32.		;ALLOW 32 BITS PER WORD
	SKIPL IMSOC5(I)
	 IMULI TT,36.		;OR 36 BITS PER WORD
	LDB E,IMSCBS
	IDIVM TT,E		;CONVERT TO NUMBER OF BYTES
	MOVEM E,IMSMPC(I)	;THAT MANY ARE FREE AT FIRST
NETOE6:	PUSHJ P,IMPSPQ		;SEARCH PENDING QUEUE (LEAVES UTCOFF)
	 JRST NETOG		;NOTHING THERE
	JUMPGE T,NETOH		;JUMP IF NOT LISTENING STATE
	MOVE W,2(Q)		;FOREIGN SOCKET NUMBER
	MOVEM W,IMSOC3(I)
	LDB H,[101000,,3(Q)]	;FOREIGN HOST IMPHTB INDEX
	DPB H,IMSCFH
	SKIPA W,[%NSRFC]
NETOH:	 MOVEI W,%NSOPN
	HRRM W,IMSOC4(I)
	JUMPGE D,NETOD1		;JUMP IF RECEIVER
	SKIPL W,3(Q)		;SKIP IF RTS, GET LINK #
	 JRST 4,.		;HE SENT STR
	DPB W,IMSCLN		;STORE LINK NUMBER
NETOD:	HRRZ Q,UUAC(U)		;CHANNEL OPEN ON
	MOVE Q,CHNBIT(Q)
	PUSHJ P,IMPUIM		;INTERRUPT SELF
	JRST NETOG		;GO FINISH THE OPEN

NETOD1:	SKIPGE W,3(Q)		;SKIP IF STR, GET BYTE SIZE
	 JRST 4,.		;HE SENT RTS
	ANDI W,377
	LDB Q,IMSCBS
	CAMN W,Q
	 JRST NETOD		;BYTE SIZES DIFFER, LOSE
	PUSHJ P,IMPBRT		;RETURN THE BUFFER
	JRST OPNL22		;SELF-CONTRADICTORY OPEN?

NETOG:	HRRZ W,UUAC(U)
	MOVS W,CHNBIT(W)
	TLO W,400000		;IN USE
	HRR W,U			;SETZ+<<INT MASK>,,<USER WHO HAS SOCKET>>
	MOVEM W,IMSOC1(I)	;WE ARE NOW FULLY SET UP TO THIS SOCKET
	CONO PI,NETON
	TLNN C,20		;SKIP IF LISTENING TYPE SOCKET
	 PUSHJ P,NETOS		;SEND RFC (CAN'T HANG, ALREADY GOT NETOW)
	PUSHJ P,LSWPOP		;UNLOCK NETOSW, NOW THAT IMSOC1 4.9 IS SET
	PUSHJ P,LSWDEL		;UNLOCK IMSOC1(I)
	PUSHJ P,LSWPOP		;REMOVE FROM LIST OF NETWORK OPENS IN PROGRESS
	HRLZ A,I		;LEFT HALF OF IOCHNM GETS SOCKET INDEX
	HLRZS C
	JSP Q,OPSLC7
	    NETDUI,,NETDUO
	    NETDBI,,NETDBO
	    NETDUI,,NETDUO
	    NETDBI,,NETDBO

;GOBBLE MAIN PROGRAM CONTROL LINK BLOCK

NETOW:	JUMPL U,NETOW1		;FROM STYNET CLOCK LEVEL
	PCLT
	SKIPGE IMPHTB(H)	;SKIP IF NOT RFNM WAIT ON LINK 0
	 PUSHJ P,UFLS
	PUSHJ P,SWTL		;GRAB CONTROL LINK BLOCK
	    IMPMPU
	SKIPL IMPHTB(H)		;DID CTL LINK TO THIS HOST GET BACK INTO RFNM WAIT?
	 POPJ P,		;NO, OK
	PUSHJ P,LSWPOP		;YES, RELEASE RESOURCE WHILE AWAITING RFNM
	JRST NETOW

;FROM NETIDC (AT CLOCK INTERRUPT LEVEL)
NETOW1:	SKIPL IMPHTB(H)
	 AOSE IMPMPU
	  CAIA		;INPUT CAN'T BE READ YET.
	   POPJ P,
	CONO PI,NETOFF
	PUSHJ P,IMPUIN	;REACTIVATE SO WILL CHECK AGAIN
	SUB P,[2,,2]	;THROW THROUGH NETI6, NETID
	JRST NETOJ1	;TAKE NO-INPUT-AVAILABLE EXIT

;WAIT FOR MEMORY SO CAN ALLOCATE BUFFER

NETMW:	PCLT			
	MOVEI T,3
	CAMG T,LMEMFR
	 JRST [	PUSHJ P,UDELAY	;MAYBE MEMORY FROZEN, GIVE CORE JOB
		JRST NETOE1 ]	;A CHANCE TO PCLSR US, THEN TRY AGAIN
	CAMLE T,LMEMFR	;SKIP WHEN MORE THAN 3K FREE
	 PUSHJ P,UFLS
	JRST NETOE1

;SEND RFC AND MAYBE ALLOCATE.  IMSOC INDEX IN I, HOST INDEX IN H.

NETOS:	PUSHJ P,STHSTM		;STORE HOST ADDRESS IN IMPMPC+n, ALSO MESSAGE TYPE
	MOVE J,[8_24.+13._8]	;BYTE SIZE = 8, BYTE COUNT = 13.
	MOVEM J,IMPMPC+6
	MOVEI J,1_4		;3 NOPS + RTS
	SKIPGE D		;SKIP IF INPUT
	 MOVEI J,2_4		;3 NOPS + STR
	MOVEM J,IMPMPC+7
	LSH A,4			;LOCAL SOCKET NUMBER
	MOVEM A,IMPMPC+10
	LSH B,4			;FOREIGN SOCKET NUMBER
	MOVEM B,IMPMPC+11
	MOVEI TT,2(I)		;LINK NUMBER FOR RECEIVE SOCKET
	SKIPGE D
	 LDB TT,IMSCBS		;BYTE SIZE FOR SEND SOCKET
	LSH TT,28.
	HRRZ J,IMSOC4(I)
	CAIE J,%NSRFC
	 CAIN J,%NSOPN		;SKIP IF CONNECTION NOT YET OPEN
	  JUMPGE D,NETOS2	;JUMP IF CONNECTION OPEN AND READ
	MOVEM TT,IMPMPC+12
	MOVEI TT,4		;TEXT LENGTH
NETOS3:	HRRM TT,IMPMPC
	JRST IMPMPQ

NETOS2:	MOVEI J,<4_8>+2(I)	;NOP + ALL + LINK #
	LSH J,4
	IOR TT,J
	MOVEM TT,IMPMPC+12
	MOVE TT,IMSOC8(I)	;SEND MESSAGE ALLOC
	LSH TT,16.+4
	MOVEM TT,IMPMPC+13
	MOVE TT,IMSOC7(I)	;SEND BIT ALLOC
	LSH TT,16.+4
	MOVEM TT,IMPMPC+14
	MOVE TT,[8_24.+22._8]	;BYTE COUNT = 22.
	MOVEM TT,IMPMPC+6
	MOVEI TT,6		;MESSAGE LENGTH
	JRST NETOS3

;.NETAC CH,	;ACCEPT CONNECTION
;ERROR RETURN
;NORMAL RETURN

ANETAC:	JSP T,NETCHK
	HRRZ T,IMSOC4(I)	;SOCKET STATE
	CAIE T,%NSRFC
	 JRST OPNL41		;NOT IN RFC RECEIVED STATE
	LDB H,IMSCFH
	PUSHJ P,NETOW		;GET IMPMPC
	MOVE A,IMSOC2(I)	;LOCAL SOCKET NUMBER
	MOVE B,IMSOC3(I)	;FOREIGN SOCKET NUMBER
	MOVE D,A
	ROT D,-1
	PUSHJ P,NETOS		;SEND RFC (AND MAYBE ALL)
	CONO PI,NETOFF
	HRRZ T,IMSOC4(I)
	MOVEI TT,%NSOPN
	CAIN T,%NSRFC
	 HRRM TT,IMSOC4(I)	;CONNECTION OPEN
	JRST NETOJ1

NETCHK:	HRRZ A,(R)
	CAIL A,NETDUI
	CAILE A,NETDBO
	 JRST OPNL34	;NOT A NETWORK CHANNEL
	HLRE I,(R)	;SOCKET TABLE INDEX
	JUMPGE I,(T)
	JRST OPNL41	;OTHER END OF PIPELINE GONE (NET WENT DOWN)
	
;.NETS CH,	;SEND BUFFER NOW
;RETURN

NETFRC:	JSP T,NETCHK	;ENTRY FROM .CALL FORCE
	MOVE T,IMSOC2(I)
	TRNN T,1
	 JRST OPNL2	;NOT SEND SOCKET
	CONO PI,NETOFF
	MOVE T,IMSMPP(I)
	CAMN T,IMSPIP(I)
	 JRST NETOJ1	;BUF EMPTY
	MOVSI TT,400000	;TURN ON SEND BUFFER BIT
	IORM TT,IMSOC4(I)
	PUSHJ P,IMPOST	;TURNS NETON
	JRST POPJ1

NETFIN:	HRRZ TT,IMSBFE(I)	;ENTRY FROM .CALL FINISH (NETFRC HAS BEEN CALLED)
	SUB TT,IMSOC6(I)	.SEE NETOE5 ;FOR COMMENTS FOR THIS CODE
	HRRZS TT
	SKIPGE IMSOC5(I)
	 IMULI TT,32.
	SKIPL IMSOC5(I)
	 IMULI TT,36.
	LDB T,IMSCBS
	IDIVM TT,T		;T NOW HAS SIZE OF OUTPUT BUFFER IN BYTES
	CAME T,IMSMPC(I)	;WAIT FOR BUFFER TO EMPTY OUT
	 PUSHJ P,UFLS
	MOVEI T,%NSRFN		;WAIT FOR RFNM
	HLL T,IMSOC4(I)		;4.9 IS KNOWN TO BE OFF NOW!
	CAMN T,IMSOC4(I)
	 PUSHJ P,UFLS
	JRST POPJ1

;.NETINT CH,	;SEND NETWORK INTERRUPT "INR" OR "INS"
	;INR FROM RECEIVER TO SENDER (LOCAL SOCKET EVEN, FOREIGN ODD)
	;INS FROM SND TO RCV ( -", -")
;ALSO .CALL NETINT, ARG 1 IS CH

NNETINT:JSP T,NETCHK
	AOSA (P)	;GOING TO WIN, SKIP RETURN
ANETINT: JSP T,NETCHK	;I<- SOCKET TABLE INDEX
	LDB H,IMSCFH	;HOST INDEX FOR NETOW
	PUSHJ P,NETOW	;WAIT FOR IMPMPU
	MOVEI A,1	;SET COUNT
	MOVEM A,IMPMPC
	PUSHJ P,STHSTM	;STORE HOST ADDRESS
	MOVE A,[8_24.+2_8]	;BYTE SIZE 8, COUNT 2
	MOVEM A,IMPMPC+6
	MOVE A,IMSOC2(I)	;LCL SOCK #
	MOVSI B,7_10.	;INR
	TRNE A,1	;SKIP IF RCV
	 MOVSI B,8_10.	;INS
	LDB A,IMSCLN	;LINK #
	DPB A,[241000,,B]
	MOVEM B,IMPMPC+7
	JRST IMPMPQ	;QUE IT, START OUTPUT (IMPOST)

;STORE HOST ADDRESS FROM H INTO LEADER IN IMPMPC.  BASHES W, Q.
STHSTM:	MOVEI Q,IMPMPL
	HRLM H,IMPMPC		;ALSO SAVE HOST INDEX FOR PI LEVEL
;STORE HOST ADDRESS FROM H INTO LEADER IN (Q), BASHES W.
STHSTP:	MOVE W,IMPHTN(H)	;FOREIGN HOST NUMBER
IFN 1,	DPB W,[103000,,3(Q)]	; Store host address
IFN 0,[	DPB W,[301000,,3(Q)]	;STORE HOST NUMBER
	LSH W,-9
	DPB W,[102000,,3(Q)]	;STORE IMP NUMBER
] ;IFN 0
	MOVSI W,17_10.		;NEW-FORMAT FLAG
	MOVEM W,2(Q)		;MESSAGE TYPE 0 (LINK, ETC. ARE ALWAYS ZERO)
	POPJ P,

;.CALL NETBLK		;WAIT FOR STATE TO CHANGE OR TIME OUT
; ARG 1 - CHANNEL
; ARG 2 - STATE
; ARG 3 - TIME, AS IN .SLEEP (OPTIONAL) (WRITTEN BACK)
; VAL 1 - NEW STATE
; VAL 2 - TIME LEFT

ANETBLK:JSP T,NETCHK
	MOVE T,I	;SAVE INDEX IN T
	HRL T,B		;STATE ALSO
	CAIGE W,3	;SKIP IF 3 ARGS (TIME GIVEN)
	 JRST ANETB3	;USE DEFAULT TIME
	TLNE C,1000	;SKIP IF POINTER, RATHER THAN IMMEDIATE
	 JRST ANETB5
	XCTR XRW,[MOVES B,(C)]	;GET TIME FROM USER (CHECK WRITE ALSO)
	JUMPL B,ANETB1	;NEG MEANS ALREADY ABS TIME
	MOVNS B		;MAKE NEG
	SUB B,TIME	;-TIME TO GO TO
ANETB1:	UMOVEM B,(C)	;STORE NEG TIME FOR PCLSR
	MOVNS B		;MAKE +
ANETB4:	MOVEM B,EPDL(U)	;ALSO USED IN B LATER
	PUSHJ P,ANETB2	;SKIP IF STATE CHANGE OR TIMEOUT
	 PUSHJ P,UFLS
	SUB B,TIME	;HOW MUCH USED?
	HRRZ A,IMSOC4(I)	;RETURN STATE
	JRST POPJ1

ANETB2:	HLR A,T		;DESIRED STATE
	XOR A,IMSOC4(T)	;CURRENT STATE
	TRNE A,-1	;SKIP IF STILL MATCH
	 JRST POPJ1
	MOVE A,EPDL(U)	;SAVED TIME HERE
	CAMG A,TIME
	 AOS (P)	;TIME OUT!
	POPJ P,

ANETB3:	HRLOI B,377777	;NO TIME SUPPLIED, USE INFINITY
	JRST ANETB4

ANETB5: HRRZ B,C	;IMMEDIATE TIME SUPPLIED
	ADD B,TIME	;(TIMEOUT WILL RESTART ON EACH PCLSR, TOO BAD)
	JRST ANETB4

IFE INETP,[
;.CALL STYNET
;ARG 1 - STY CHANNEL
;ARG 2 - NET INPUT CHANNEL TO CONNECT STY OUTPUT TO, OR -1 TO DISCONNECT
;ARG 3 - NET OUTPUT CHANNEL TO CONNECT STY INPUT TO
;ARG 4 - CHARS TO SEND WHEN OUTPUT .RESET HAPPENS ON STY'S TTY
;	   UP TO 3 8-BIT CHARACTERS, LEFT JUSTIFIED.

NSTYNT:	TLNN R,%CLSST
	 JRST OPNL34		;1ST ARG NOT A STY CHANNEL.
	HLRZ I,(R)		;GET TTY # OF STY
	HRRES B			;ALLOW IMMEDIATE -1
	JUMPGE B,NSTYN2		;JUMP IF CONNECTING.
	PUSHJ P,NSTYN0		;DISCONNECT
	 JRST OPNL41		;WASN'T CONNECTED
	JRST POPJ1

;VARIOUS ROUTINES CALL HERE WITH THE TTY# OF A STY IN I, TO DISCONNECT THE
; STY FROM THE NETWORK.  NOTE THIS ROUTINE MUST NOT CHANGE U AND MUST NOT
; LSWCLR, SINCE IT COULD BE CALLED FROM IODCL VIA STYCLS OR NETCLS.

NSTYN0:	MOVSI B,%SSNET		;DISCONNECTING BOTH SIDES.
	CONO PI,NETOFF
	TDNN B,STYSTS-NFSTTY(I)
	 POPJ P,			;THIS STY NOT CONNECTED?
	ANDCAB B,STYSTS-NFSTTY(I)	;MARK AS NO LONGER CONNECTED
	MOVE C,STYNTL-NFSTTY(I)		;REMOVE THIS STY FROM ACTIVATION LIST
	MOVEI D,STYNTA-STYNTL+NFSTTY
NSTYN1:	CAMN I,STYNTL-NFSTTY(D)		;FIND THE STY THAT POINTS TO THIS ONE,
	 MOVEM C,STYNTL-NFSTTY(D)	;AND PATCH US OUT OF THE LIST.
	SKIPE D,STYNTL-NFSTTY(D) 	;SEARCH WHOLE LIST TILL FIND WHO POINTS TO US.
	 JRST NSTYN1
	SETOB C,STYNTL-NFSTTY(I)
	EXCH C,STYNTI-NFSTTY(I)	;MARK THIS STY AS HAVING NO CONNECTION, GET SOCKET INDICES
IFN CHAOSP,[
	TLNE B,%SSCHA
	 JRST [	MOVSI B,%SSCHA	;DISCONNECT FROM CHAOS NET
		ANDCAM B,STYSTS-NFSTTY(I)
		MOVSI B,%CFSTY
		TDNN B,CHSSTA(C)
		 JRST 4,.	;CHAOS DOESN'T THINK IT WAS CONNECTED?
		ANDCAM B,CHSSTA(C)
		JRST NETOJ1 ]
];CHAOSP
	MOVE B,[40000,,777]
	TDNN B,IMSOC5(C)
	 JRST 4,.		;SOCKET DOESN'T THINK IT WAS CONNECTED?
	ANDCAM B,IMSOC5(C)	;AND MARK SOCKETS WE WERE CONNECTED TO AS DISCONNECTED
	MOVSS C
	TDNN B,IMSOC5(C)
	 JRST 4,.		;SOCKET DOESN'T THINK IT WAS CONNECTED?
	ANDCAM B,IMSOC5(C)
	JRST NETOJ1

NSTYN2:	MOVE Q,I		;SAVE TTY # OF STY
	MOVEI E,1
	MOVE A,B		;DECODE THE NETWORK INPUT CHANNEL
	JSP T,CHNDCD
IFN CHAOSP,[
	HRRZ A,(R)
	CAIE A,CHAIDN
	 CAIN A,CHAODN
	  JRST [ HLRZ I,(R)	;CONNECT TO CHAOS NET
		 CONO PI,NETOFF
		 MOVSI B,%CFSTY
		 TDNE B,CHSSTA(I)
		  JRST OPNL23	;ALREADY CONNECTED, FILE LOCKED
		 MOVSI C,%SSNET+%SSCHA
		 TDNE C,STYSTS-NFSTTY(Q)
		  JRST OPNL23	;ALREADY CONNECTED, FILE LOCKED
		 IORM B,CHSSTA(I)	;OK, HOOK UP
		 DPB Q,[$CFTTN,,CHSSTA(I)]
		 JRST NSTYN3 ]
];CHAOSP
	JSP T,NETCHK	;TEST LEGALITY;  OPNL IF LOSES
	TDNE E,IMSOC2(I)
	 JRST OPNL2		;WRONG DIRECTION IF IT'S AN OUTPUT CHANNEL
	MOVE B,I		;SAVE INPUT IMSOC INDEX
	MOVE A,C		;DECODE OUTPUT CHANNEL
	JSP T,CHNDCD
	JSP T,NETCHK
	TDNN E,IMSOC2(I)
	 JRST OPNL2		;WRONG DIRECTION IF INPUT SOCKET
	CONO PI,NETOFF
	MOVE E,[40000,,777]
	TDNN E,IMSOC5(B)	;ERROR IF EITHER CHANNEL ALREADY CONNECTED
	 TDNE E,IMSOC5(I)
	  JRST OPNL23		;"FILE LOCKED"
	MOVSI C,%SSNET
	TDNE C,STYSTS-NFSTTY(Q)
	 JRST OPNL23		;SIMILAR ERROR IF STY ALREADY CONNECTED
	HRR E,Q			;GET 40000,,TTY #
	IORM E,IMSOC5(I)
	IORM E,IMSOC5(B)	;MARK SOCKETS AS CONNECTED
NSTYN3:	SKIPGE STYNTL-NFSTTY(Q)	;HALT IF STY'S VARS ARE NOT CORRECT FOR A 
	 SKIPL STYNTI-NFSTTY(Q)	;NON-CONNECTED STY.
	  JRST 4,.
	IORM C,STYSTS-NFSTTY(Q)	;ALL ERROR CAUGHT, SO MARK STY CONNECTED.
	HRL B,I			;PUT INPUT IMSOC IDX,, OUTPUT IMSOC IDX
	MOVSM B,STYNTI-NFSTTY(Q) ;INTO THE STY
	TRZ D,7777		;STORE THE OUTPUT RESET CHARACTERS - AT MOST 3
	MOVEM D,STYORC-NFSTTY(Q)
IFN CHAOSP,[			;ACTIVATE IN CASE HAS UNREAD INPUT
	TLNN C,%SSCHA
	 PUSHJ P,IMPUIN
	TLNE C,%SSCHA
	 PUSHJ P,CHINTI
];CHAOSP
.ELSE	PUSHJ P,IMPUIN
	JRST NETOJ1
] ;IFE INETP

SUBTTL	ARPANET MP I/O ROUTINES

IFE INETP,[
;CALL STYNTC AT CLOCK LEVEL TO PROCESS ALL NECESSARY TRANSFERS OF DATA
;BETWEEN CONNECTED STYS AND NET SOCKETS

STYNTC:	CONO PI,NETOFF
	SKIPN I,STYNTA		;GET HEAD OF ACTIVATE LIST
	 JRST NETONJ		;EMPTY
	SETZM STYNTA		;COPY LIST IN CASE A STY IS PUT BACK ON
	CONO PI,NETON
STYNT7:	MOVE A,STYNTL-NFSTTY(I)	;GET NEXT ON LIST
	MOVEM A,STYNTB		;SAVE FOR NEXT TIME AROUND LOOP
	SETOM STYNTL-NFSTTY(I)	;THIS ONE IS NO LONGER ON ACTIVATE LIST
	MOVE A,STYSTS-NFSTTY(I)
	TLNN A,%SSNET
	 JRST 4,.		;STY CLAIMS NOT TO BE CONNECTED??
	MOVE R,I		;SAVE TTY #
IFN CHAOSP,[
	TLNE A,%SSCHA
	 JRST STYCHA		;CONNECTED TO CHAOS NET
];CHAOSP
] ;IFE INETP
IFN INETP,STYNCP:

	SKIPGE TTYOAC(I)
	 JRST STYNT1		;NO OUTPUT, CHECK FOR INPUT
;HANDLE OUTPUT TO NET
	HRRZ I,STYNTI-NFSTTY(I)	;GET IMSOC IDX OF OUTPUT CHANNEL
	MOVSI A,40000
	TDNN A,IMSOC5(I)
	 JRST 4,.		;SOCKET CLAIMS NOT TO BE CONNECTED??
STYNT5:	CONO PI,NETOFF		;INCLUDES TTYOFF
	PUSHJ P,NSOSE0		;CAN WE OUTPUT TO NET NOW?
	 JRST STYNT6		;NO, WAIT TILL LATER, PI LVL WILL REACTIVATE WHEN STATE CHANGES
	LDB T,IMSCBS		;SINCE THIS IS PI LEVEL,
	MOVE Q,IMSOC7(I)	;NO POINT IN SENDING MORE OUTPUT THAN ALLOCATED
	SUB Q,IMSC7I(I)
	IDIVM Q,T		;T GETS NUMBER OF BYTES ALLOCATED AND NOT BUFFERED
	CAMLE E,T
	 MOVE E,T
	JUMPLE E,STYNT6		;NO ALLOC, SEND NOTHING
	EXCH R,I		;BEFORE EXCH, R HAS TTY #, I HAS NET IMSOC IDX
	MOVEM D,DBBBP		;SET UP BUFFER-POINTING VARS FOR TTY OUTPUT INTERRUPT LEVEL
	MOVEM E,DBBCC
	MOVEM E,DBBCC1
	PUSH P,R
	SETOM TYPNTF
	PUSHJ P,TYP		;OUTPUT THROUGH THOSE POINTERS, INTO THE NET CHNL BUFFER
	SETZM TYPNTF
	POP P,R
	EXCH I,R
	MOVE D,DBBBP
	MOVE E,DBBCC
	MOVE Q,DBBCC1
	PUSHJ P,NSOFIN		;FIGURE OUT HOW MANY CHARS WERE TYPED, AND UPDATE SOCKET.
	 JRST STYNT4		;MORE ROOM IN BUFFER => MAYBE TYPE SOME MORE.
	JRST STYNT6		;ELSE TRY INPUT FROM NET, BUT SEND WHATEVER WE GOT

STYNT4:	SKIPL TTYOAC(R)		;MORE OUTPUT IN TTY BUFFER?
	 JRST STYNT5		;YES, PROCESS IT
STYNT6:	PUSHJ P,NSOFN1		;NO, BE SURE NET BUFFER GETS SENT SOON

;HERE TO TRY TO HANDLE INPUT FROM NET
STYNT1:	HLRZ I,STYNTI-NFSTTY(R)	;INPUT IMSOC INDEX
	MOVSI A,40000
	TDNN A,IMSOC5(I)
	 JRST 4,.		;SOCKET CLAIMS NOT TO BE CONNECTED?
STYNT2:	PUSHJ P,NETIDC		;GET CHAR FROM NET SOCKET
	 JRST STYNT3		 ;GOT CHAR IN W
	 JRST STYNT8		 ;NO CHAR AVAIL, HANDLE OTHER STYS
				 ;2 SKIPS => GIVE UP, SPECIAL CHARACTER SEEN, OR BAD STATE
	PUSHJ P,IMPUIP		;WAKE UP THE TELNET SERVER
	MOVE I,R		;DISCONNECT THE STY AND SOCKETS
	PUSHJ P,NSTYN0
	 JRST 4,.
IFE INETP,[
STYNT8:	SKIPE I,STYNTB		;GET NEXT STY FROM COPIED ACTIVATION LIST
	 JRST STYNT7
	POPJ P,
] ;IFE INETP
.ELSE	JRST STYNT8

STYNT3:	EXCH I,R		;HERE IF GET CHAR FROM NET IN W.  I GETS TTY #.
	PUSH P,R
	PUSH P,I
	MOVE A,W
	CONO PI,TTYOFF
	PUSHJ P,NTYI5		;GIVE CHARACTER TO TTY INPUT INTERRUPT LEVEL.
	CONO PI,TTYON
	POP P,R			;TTY #;  POP IN REVERSE ORDER TO UNDO THE EXCH
	POP P,I			;IMSOC IDX
	JRST STYNT2		;TRY TO GET ANOTHER INPUT CHARACTER.

;STYNTC'S INTERFACE TO NET INPUT IOT.
;I HAS IMSOC IDX OF INPUT SOCKET.
;1 SKIP => NO DATA AVAILABLE.
;2 SKIPS => TELNET CONTROL CHARACTER FOUND, SO DISCONNECT STY AND
;INTERRUPT THE USER PROGRAM.
NETIDC:	MOVNI U,1		;U=-1 TELLS NETI IT CAME FROM HERE
	HRRZ H,IMSOC4(I)	;CHECK SOCKET STATE
	CAIN H,%NSOPN
	 JRST POPJ1		;NO DATA
	CAIGE H,%NSCLI		;SKIP IF IN ONE OF THE TWO INPUT AVAILABLE STATES
	 JRST POPJ2		;STATE IS ABNORMAL, SO DISCONNECT FROM STY.
	JRST NETID		;ELSE TRY AN IOT.

;NETWORK UNIT INPUT.
NETI:	HRRE I,A	;SOCKET TABLE INDEX
	JUMPL I,IOCER1
NETIB:	MOVE A,IMSOC5(I) ;ENTER HERE FROM BLOCK-MODE INPUT
	TLNE A,40000
	 JRST IOCR10	;CAN'T IOT AT M.P. LEVEL WHILE SOCKET CONNECTED TO A STY.
NETID:	MOVE A,IMSC8I(I)
	LDB B,IMSCBS
	IMUL B,IMSMPC(I)
	ADD B,IMSOC7(I)	;TOTAL NUMBER OF BITS YET TO BE READ
	CAIGE A,8.	;IF MESS REALL OF 8 OR MORE
	 CAMG B,IMSC7I(I) ;OR BIT REALL SATISFIES "DOUBLE BUFFERING" CRITERION
	  PUSHJ P,NETI6	;THEN SEND ALLOCATE
	JUMPL U,NETI4	;JUMP IF READING INPUT TO GIVE DIRECTLY TO A STY
NETI0:	CONO PI,NETOFF	;DON'T ALLOW INTO IMPUIN WHILE CHECKING STATE, #BITS
	HRRZ A,IMSOC4(I)
	JUMPE A,NETIB1	;CONNECTION CLOSED
	CAIE A,%NSINP
	 CAIN A,%NSCLI
	  JRST .+3
	   CAIE A,%NSOPN
	    JRST IOCR10		;SOCKET IN BAD STATE
	PCLT
	SKIPG IMSMPC(I) 	;WAIT FOR BITS TO ARRIVE
	 PUSHJ P,UFLS
	CONO PI,NETON	  	;NETON IN CASE DIDN'T UFLS
	SKIPG IMSMPC(I) 	;DID THEY?
	 JRST NETI0		;NO, STATE MUST HAVE CHANGED, CHECK IT AGAIN

NETI4:	SOSL IMSOCT(I)		;TAKE BYTE
	 JRST NETI4A
	MOVE A,IMSMPP(I)	;END OF MESSAGE, FIND ADDRESS OF NEXT HEADER WORD
	MOVEI A,1(A)		;WHICH IS IN NEXT WORD AFTER LAST BYTE LOADED
	CAILE A,@IMSBFE(I)
	 HRRZ A,IMSOC6(I)	;WRAP AROUND
	SOSGE B,(A)		;GET HEADER WORD, COUNT DOWN FOR BYTE ABOUT TO TAKE
	 JRST 4,.		;NO MESSAGE, ALTHOUGH IMSMPC > 0
	MOVEM B,IMSOCT(I)	;SAVE # BYTES LEFT IN THIS MESSAGE
	HLL A,IMSBFE(I)		;SET UP BYTE POINTER LH TO LAST BYTE IN WORD
	MOVEM A,IMSMPP(I)	; SO ILDB WILL GET FIRST DATA BYTE OF THIS MSG
	AOS IMSC8I(I)		;INCREASE MESSAGE ALLOCATION
NETI4A:	MOVE TT,IMSMPP(I)	;CHECK FOR WRAP-AROUND
	MOVE H,IMSOC5(I)
	TLNE H,2000
	 JRST NETI2		;JUMP IF ONE BIT BYTES
	CAMN TT,IMSBFE(I)
	 JRST [	HRRZ TT,IMSOC6(I)
		HLL TT,IMSPIP(I)	;B.P. TO FIRST BYTE IN BUFFER
		JRST .+1 ]
	ILDB W,TT
	JRST NETI3

NETI2:	LDB E,IMSCBS		;BITS PER BYTE
	MOVEI W,0
NETI1:	CAME TT,IMSBFE(I)
	 JRST NETI1A
	HRRZ TT,IMSOC6(I)	;WRAP AROUND
	HLL TT,IMSPIP(I)
NETI1A:	ILDB A,TT
	LSH W,1
	IORI W,(A)
	SOJG E,NETI1
;DROPS THROUGH
;DROPS IN

NETI3:	TRNN W,200		;IS THIS A TELNET CONTROL CHAR (>= 200)?
	 JRST NETI3A
	JUMPL U,[AOS IMSOCT(I)	;YES;  IF DIRECT-CONNECTED TO A STY, BREAK CONNECTION.
		 JRST POPJ2]	; WITHOUT GOBBLING THAT CHARACTER
	TLNE H,400		;IF 7-BIT ASCII MODE, REPLACE CHARACTER BY ^@.
	 SETZ W,
NETI3A:	MOVEM TT,IMSMPP(I)
	LDB TT,IMSCBS
	ADDM TT,IMSC7I(I)	;INCREASE BIT ALLOCATION
	CONO PI,NETOFF		;WHILE CHANGING STATE
	SOSLE IMSMPC(I)		;ONE LESS BYTE IN BUFFER
	 JRST NETONJ		;OK, THERE IS MORE IN BUFFER
	MOVNI E,1		;YES, STATE IS CHANGING.
	HRRZ A,IMSOC4(I)
	CAIN A,%NSCLI
	 MOVEI E,%NSCLS
	CAIN A,%NSINP
	 MOVEI E,%NSOPN		;NO INPUT AVAILABLE
	JUMPL E,[JRST 4,.]	;WAS IN SOME RANDOM STATE
	CAIN E,%NSCLS
	 PUSHJ P,IMPUIP		;IF STATE CHANGING TO "CLOSED", GIVE USER AN INTERRUPT.
	HRRM E,IMSOC4(I)
	JRST NETONJ

;COME HERE WHEN INPUT IOT FINDS THAT CONNECTION IS CLOSED
NETIB1:	CONO PI,NETON
	LDB D,IMSCLS
	CAIE D,%NCFRN
	 JRST IOCR10	;ABNORMAL CLOSURE, GIVE IOCER INSTEAD OF EOF
	MOVE TT,IMSOC5(I)
	POP P,D		;GET OUR RETURN ADDRESS.
	ANDI D,-1
	CAIE D,AIOT3	;IF WE ARE NOT DOING A UNIT MODE IOT,
	 JRST 1(D)	;JUST RETURN WITH 1 SKIP.
	TLNN TT,1400	;SKIP IF ASCII MODE
	 JRST IOCER2	;EOF IN IMAGE MODE IS IOCERROR.
	HRROI W,EOFCH	;EOF IN ASCII MODE RETURNS ^C.
	JRST 1(D)

NETI6:	HRRZ H,IMSOC4(I)	;SEND ALL MSG
	CAIE H,%NSINP
	 CAIN H,%NSOPN
	  CAIA
	   POPJ P,	;CLOSED, DON'T SEND ALLOCATE
	LDB H,IMSCFH	;HOST INDEX FOR NETOW
	PUSHJ P,NETOW	;GOBBLE MAIN PROG CONTROL LINK BLOCK
	MOVEI J,2(I)	;LINK #
	IORI J,<4_8>	;SEND ALLOC
	LSH J,16.
	ADD J,IMSC8I(I)
	LSH J,4
	MOVEM J,IMPMPC+7
	MOVE J,IMSC7I(I)
	LSH J,4
	MOVEM J,IMPMPC+10
	PUSHJ P,STHSTM		;STORE HOST ADDRESS, MESSAGE TYPE
	MOVE J,[8_24.+8_8]
	MOVEM J,IMPMPC+6
	MOVEI J,2
	HRRM J,IMPMPC	;TEXT LENGTH
	SETZB A,TT
	EXCH A,IMSC8I(I)
	EXCH TT,IMSC7I(I)
	ADDM A,IMSOC8(I)
	ADDM TT,IMSOC7(I)
	JRST IMPMPQ

;UNIT MODE NETWORK OUTPUT (DOESN'T CLOBBER C)
	JRST NETSIO	;SIOT VECTOR
NETW:	HRRE I,A	;SOCKET TABLE INDEX
	JUMPL I,IOCER1
	SKIPGE C
	 SKIPA A,(C)
	  UMOVE A,(C)
NETWB:	CONO PI,NETOFF		;BYTE TO OUTPUT IN A. HERE FROM BLOCK MODE.
	HRRZ B,IMSOC4(I)
	CAIE B,%NSOPN
	CAIN B,%NSRFN
	 JRST .+2
	  JRST IOCR10
	SKIPG IMSMPC(I)		;SKIP IF ROOM TO PUT BYTE IN BUF
	 JRST [	MOVSI B,400000
		IORM B,IMSOC4(I) ;SET TO SEND IT NOW
	IFN DMIMP,CONSZ FI,70
		 PUSHJ P,IMPIOS
		SKIPG IMSMPC(I)  ;WAIT FOR AT LEAST ONE BYTE OF ROOM
		 PUSHJ P,UFLS
		CONO PI,NETON
		SKIPG IMSMPC(I)
		 JRST NETWB	;NO ROOM, STATE MUST HAVE CHANGED
		JRST .+1]
	MOVE E,IMSOC5(I)
	MOVE T,IMSOC7(I)
	TLNE E,100000
	 CAML T,IMSC7I(I)
	  JRST NETW4
	MOVSI B,400000		;ALLOCATION USED UP (AND FEATURE ENABLED)
	IORM B,IMSOC4(I)	;SEND BUFFER NOW
	PUSHJ P,IMPOST
	CAMN T,IMSOC7(I)	;WAIT FOR DATA TO GO OUT OR ALLOC TO COME IN
	 PUSHJ P,UFLS
	JRST NETWB		;TRY AGAIN

NETW4:	MOVE T,IMSMPP(I)	;GET POINTER
	MOVE E,TIME
	CAMN T,IMSPIP(I)	;SKIP UNLESS BUFFER EMPTY
	 MOVEM E,IMSOCT(I)	;SET TIME FOR FIRST BITS INTO BUF
	LDB B,IMSCBS		;BYTE SIZE
	MOVE E,IMSOC5(I)	;FLAGS
	CONO PI,NETOFF		;WANT TO MUNG POINTERS WITHOUT PI INTERFERENCE
	TLNE E,2000		;SKIP IF BYTES FIT EXACTLY IN WORD
	 TLNN T,770000		;SKIP IF NOT AT RIGHT END OF WORD
	  JRST NETW2		;IDPB, CHECK FOR POINTER WRAP
	LDB TT,[360600,,T]	;GET BYTE POS
	CAML TT,B		;SKIP IF BYTE SPLITS ACROSS WORDS
	 JRST NETW1		;JUST DO IDPB
	DPB TT,[301400,,T]	;SET BYTE TO STORE IN RIGHT OF THIS WORD
	SUB TT,B		;=> -(# OVERFLOW BITS)
	ROT A,(TT)		;HIGH PART OF BYTE IN RIGHT END OF A
	DPB A,T			;STORE PART BYTE
	AOS T,IMSMPP(I)		;INCR TO NEXT WORD
	MOVEI E,(T)
	CAILE E,@IMSBFE(I)
	 HRR T,IMSOC6(I)	;WRAP
	MOVEM A,@T		;STASH REST OF BYTE IN LEFT PART OF NEXT WORD
	ADDI TT,36.		;SET TO NEW POSITION
	DPB TT,[360600,,T]	;NEW BYT POS
	MOVEM T,IMSMPP(I)	;STORE UPDATED PTR
	JRST NETW3		;WRAP UP

;DEPOSIT A BYTE WHICH MAY WRAP AROUND

NETW2:	CAME T,IMSBFE(I)
	 JRST NETW1		;NO WRAP
	HRR T,IMSOC6(I)
	TLO T,440000
	MOVEM T,IMSMPP(I)

;DEPOSIT BYTE KNOWN TO FIT IN WORD

NETW1:	IDPB A,IMSMPP(I)	;STORE IT

;COUNT THE BITS NOW

NETW3:	SOS IMSMPC(I)		;1 BYTE LESS FREE
	LDB T,IMSCBS
	ADDM T,IMSC7I(I)
	JRST NETONJ

;NETWORK OUTPUT SIOT
NETSIO:	CONO PI,NETOFF
	PUSHJ P,NSOSET		;SET UP FOR FAST SIOT
	 JRST NSIOT1		;CHANNEL ISN'T SET UP FOR IT => USE NORMAL SIOT LOOP.
	PUSH P,B
	PUSH P,C
NETSO0:	XCTR XRW,[MOVES B,@-1(P)]	;COPY ARGS
	XCTR XRW,[MOVES C,@(P)]
NETSO1:	IBP B		.SEE NSIOOL ;FOR WHY THIS HAIR IS NEEDED
	XCTRI XR,[MOVE TT,(B)]
	 SKIPA T,B
	  JRST NETSO3		;PAGE FAULT, CLEAN UP IMSMPP BEFORE TAKING IT
	HRRI T,TT
	LDB TT,T
	IDPB TT,D
	SOS E
	UMOVEM B,@-1(P)		;UPDATE USER'S ARGS
	XCTR XRW,[SOSLE C,@(P)]
	 JUMPG E,NETSO1		;LOOP IF BOTH USER AND SYSTEM WILLING
	SKIPL E
	 SKIPGE C
	  JRST 4,.		;WENT TOO FAR!!
	PUSHJ P,NSOFIN		;FINISH UP HACKING NET CHANNEL.
	 JRST NETSO2		;OUTPUT BUFFER HAS MORE ROOM
	JUMPLE C,PPBAJ1		;NO ROOM BUT DON'T WANT ANY MORE ANYWAY, SO RETURN
	SKIPG IMSMPC(I)		;NO ROOM, WAIT FOR SOME
	 PUSHJ P,UFLS		;NOTE ANY STATE CHANGE WILL UNHANG
	POP P,C			;NOW TRY TO SIOT SOME MORE
	POP P,B
	MOVE D,IOTTB(H)		;RESTORE D IN CASE GOES TO NSIOT1
	JRST NETSIO

NETSO3:	PUSHJ P,NSOFIN		;TOOK PAGE FAULT, CLEAN UP
	 JFCL
	PUSHJ P,TPFLT
NETSO2:	JUMPLE C,PPBAJ1		;BUFFER HAS ROOM BUT NO DESIRE TO SEND ANY MORE, RETURN
	CONO PI,NETOFF
	PUSHJ P,NSOSE0		;SET UP TO SEND MORE
	 JRST IOCR10		;STATE MUST HAVE GONE BAD
	JRST NETSO0		;OK, SEND MORE

;SET UP FOR NET OUTPUT SIOT, OR (NSOSE0) FOR DIRECT OUTPUT FROM STY.
;AT ENTRY, A HAS LH(IOCHNM).
;CALL WITH NETOFF, AND DON'T TURN IT BACK ON BEFORE CALLING NSOFIN,
;BECAUSE WE HAVE A COPY OF IMSMPP IN D, AND PI LEVEL MIGHT BE TRYING TO MUNG IT.
;SETS D TO POINTER, E TO COUNT OF CHARS OF SPACE, AND Q TO COPY OF COUNT.
;SETS I TO IMSOC IDX.  CLOBBERS T AND TT.
;NO SKIP => CAN'T USE FAST SIOT, OR CAN'T DO DIRECT OUTPUT AT THIS MOMENT.
;IN THAT CASE, D HASN'T BEEN CLOBBERED YET.
NSOSET:	HRRE I,A
	JUMPL I,IOCER1
NSOSE0:	MOVE E,IMSOC5(I)
	HRRZ T,IMSOC4(I)
	CAIE T,%NSOPN
	 CAIN T,%NSRFN		;STATE BAD, OR BYTES CROSS WORD BOUNDARIES,
	  TLNE E,2000
	   JRST NETONJ		;IMPLIES CAN'T WIN THIS WAY.
	SKIPG E,IMSMPC(I)
	 JRST NSOFN1		;JUMP IF BUFFER FULL, SET SEND BUFFER AND NETONJ
	MOVE D,IMSMPP(I)
	CAME D,IMSBFE(I)
	 JRST NSOSE2
	HRR D,IMSOC6(I)		;IF BUFFER STORING PTR POINTS AT END OF BUFFER,
	TLO D,440000		;WRAP AROUND.
NSOSE2:	LDB Q,IMSCBS
	MOVEI TT,36.
	SKIPGE IMSOC5(I)
	 MOVEI TT,32.
	IDIVM TT,Q		;GET # BYTES/WD OF CONNECTION.
	HRRZ TT,IMSBFE(I)
	SUBI TT,(D)
	IMUL TT,Q		;# BYTES BETWEEN POINTER AND END OF BUFFER.
	LDB T,[360600,,D]
	LDB Q,IMSCBS
	IDIVM T,Q		;# BYTES NOT STORED IN WORD POINTER POINTS AT
	ADD TT,Q		;THEY ARE AVAILABLE, TOO.
	CAML E,TT
	 MOVE E,TT		;GET MINIMUM OF FULL BYTES AND BYTES AFTER THE POINTER.
	MOVE T,TIME
	MOVE Q,IMSMPP(I)
	CAMN Q,IMSPIP(I)	;SKIP IF BUFFER NOT EMPTY
	 MOVEM T,IMSOCT(I)	;TIME FOR FIRST BITS INTO BUF.
	CAILE E,600		;DON'T LEAVE NETOFF FOR MORE THAN ONE CLOCK TICK OR SO
	 MOVEI E,600
	MOVE Q,E		;ORIGINAL E. (FOR NSOFIN)
	JRST POPJ1

;FINISH UP AFTER NET OUTPUT SIOT OR DIRECT OUTPUT FROM STY.
;SKIP IF BUFFER FULL
;ASSUME Q,I LEFT OVER FROM NSOSET, AND D,E ADVANCED BY STORING CHARS.
NSOFIN:	PI2SAF			;NETOFF SHOULD STILL BE IN EFFECT FROM NSOSET
	SUBM E,Q		;- <# BYTES XFERED>
	JUMPE Q,NETONJ		;IF OUTPUT NO BYTES, DON'T CHANGE IMSMPP (IMPORTANT!)
	MOVEM D,IMSMPP(I)	;UPDATE STORING POINTER OF SOCKET BUFFER
	LDB TT,IMSCBS
	IMUL TT,Q
	MOVNS TT
	ADDM TT,IMSC7I(I)	;INCREASE COUNT OF BITS IN BUFFER
	ADDB Q,IMSMPC(I)	;UPDATE COUNT OF FREE SPACE IN BUFFER.
	JUMPG Q,.+2		;ANY SPACE LEFT => NO SKIP.
	 AOS (P)		
	JUMPG E,NETONJ		;ONLY SEND BUFFER IF CALL OUTPUT ALL IT COULD
NSOFN1:	MOVSI TT,400000		;SEND BUFFER NOW.
	IORM TT,IMSOC4(I)
	JRST IMPOST		;TURNS NETON

NETBO:	HRRE I,A
	JUMPL I,IOCER1
	XCTR XRW,[MOVES D,(C)]	;TAKE TRAP GETTING POINTER IF SWAPPED OUT
	MOVE E,IMSOC5(I)
	TLNE E,1400	;SKIP IF IMAGE MODE
	 JRST NETBOA	;ASCII MODE
	JUMPGE D,CPOPJ		;TRANSFER NO WORDS
NETBO1:	UMOVEM D,(C)
	UMOVE A,(D)
	PUSHJ P,NETWB
	UMOVE D,(C)
	AOBJN D,NETBO1
	UMOVEM D,(C)
	POPJ P,

NETBOA:	TLNN E,400	;SKIP IF 7 BIT
	 JRST NETBA8
	MOVEI E,NETBOR
	JRST NBTOCH

NETBOR:	PUSH P,D
	PUSH P,TT
	PUSHJ P,NETWB
	POP P,TT
	POP P,D
	MOVEI E,NETBOR
	POPJ P,

NETBA8:	XCTR XRW,[MOVES D,(C)]
	LDB TT,[410300,,D]
	CAIGE TT,4	;ONLY 4 BYTES PER WORD (3 < CNT < 8)
	 POPJ P,
	SKIPA TT,NETCHT-4(TT)
NTBA8A:	 UMOVEM D,(C)
	UMOVE W,(D)
	ILDB A,TT
	PUSH P,TT
	PUSHJ P,NETWB
	POP P,TT
	UMOVE D,(C)
	ADD D,[700000,,]	;ADVANCE CHAR CNT
	JUMPL D,NTBA8A		;GO TO NEXT CHAR
	MOVE TT,NETCHT+3
	ADD D,[400001,,1]	;INCR TO NEXT WORD
	JUMPL D,NTBA8A
	UMOVEM D,(C)
	POPJ P,

NETCHT:	REPEAT 4,<44-<3-.RPCNT>*10>_12.+1000,,W

NETBI:	HRRE I,A
	JUMPL I,IOCER1
	XCTR XRW,[MOVES D,(C)]	;ENSURE POINTER WILL BE WRITABLE
	MOVE E,IMSOC5(I)
	TLNE E,1400	;SKIP IF IMAGE MODE
	 JRST NETBIA	;ASCII MODE
NETBI1:	UMOVEM D,(C)	;STORE BACK POINTER
	XCTR XRW,[MOVES (D)]	;ENSURE BYTE WILL BE WRITABLE
	PUSH P,C
	PUSHJ P,NETIB	;GET NEXT BYTE
	 CAIA		;NORMAL RETURN.
	  JRST POP1J	;NO INPUT AVAIL.
	POP P,C
	UMOVE D,(C)
	UMOVEM W,(D)
	AOBJN D,NETBI1
	UMOVEM D,(C)
	POPJ P,

NETBIA:	TLNN E,400	;SKIP IF 7 BIT ASCII
	 JRST NTBIA8
	MOVEI E,NETBIR
	JRST INBTCH

NETBIR:	PUSHJ P,NETI
	 JRST [ MOVEI E,NETBIR	;INPUT IN W
		POPJ P, ]
	MOVE E,[600000,,NETBCC] ;NO INPUT AVAIL
	JRST POPJ1

NETBCC:	MOVEI H,EOFCH
	JRST POPJ2

NTBIA8:	HRRZS E			;8-BIT ASCII BLOCK MODE
	XCTR XRW,[MOVES D,(C)]
	LDB TT,[410300,,D]
	CAIGE TT,4
	 POPJ P,
	SKIPA TT,NETCHT-4(TT)
NTBI8A:	 UMOVEM D,(C)
	XCTR XRW,[MOVES (D)]
	JUMPL E,NTBI8B
	PUSH P,C
	PUSH P,TT
	PUSHJ P,NETIB
	 JRST [ MOVEI E,0
		JRST NETBI5 ]	;NORMAL RETURN - BYTE IN W.
	MOVSI E,600000		;NO BYTES AVAIL - SOCKET CLOSED.
NETBI5:	MOVE H,W
	POP P,TT
	POP P,C
	UMOVE D,(C)
	LDB W,[410300,,D]
	CAIN W,7
	 TLNN E,200000
	  JRST NTBI8C
	POPJ P,
NTBI8C:	UMOVE W,(D)
	IDPB H,TT
	UMOVEM W,(D)
	ADD D,[700000,,]
	JUMPL D,NTBI8A
	MOVE TT,NETCHT+3
	ADD D,[400001,,1]
	SKIPL E
	 JUMPL D,NTBI8A
	UMOVEM D,(C)
	POPJ P,

NTBI8B:	MOVEI H,EOFCH
	UMOVE D,(C)
	JRST NTBI8C

NETCLS:	HRRE I,A	;SOCKET TABLE INDEX
	JUMPL I,CPOPJ
	MOVE T,IMSOC2(I)
	TRNN T,1	;SKIP IF SEND SOCKET
	 JRST NETCL2
	MOVSI T,400000
	IORM T,IMSOC4(I)	;CAUSE BUFFER TO BE SENT
	PUSHJ P,IMPOST
NETCL2:	MOVSI B,600000
	CONO PI,CLKOFF
	IORM B,IMSOC1(I)	;MARK CHANNEL TO BE CLOSED
	AOS IMNCS
	HRRZ R,UUAC(U)
	MOVE A,CHNBIT(R)
	TDNE A,MSKST2(U)
	 ANDCAM A,IFPIR(U)
	MOVE I,IMSOC5(I)	;IF CHANNEL CONNECTED TO A STY,
	TLNN I,40000
	 JRST CLKONJ
	ANDI I,777		;DISCONNECT THEM.
	PUSHJ P,NSTYN0
	 JRST 4,.
	JRST CLKONJ

;SEARCH PENDING QUEUE FOR LOCAL SOCKET NUMBER IN A,
;T 4.9 = 1 => LISTENING, 4.9 => 0 => ALSO CHECK
;FOREIGN SOCKET NUMBER IN B AND FOREIGN HOST NUMBER (IMPHTB INDEX) IN H
;SKIPS IF ENTRY IS FOUND.  RETURNS ENTRY TO FREE LIST.
;Q GETS ADDRESS OF ENTRY BLOCK.  RETURN WITH NETOFF

IMPSPQ:	CONO PI,NETOFF
IMSPQP:	SKIPGE Q,IMPBPQ	;BEGINNING OF QUEUE
	 POPJ P,	;QUEUE EMPTY
	MOVNI J,1	;PREVIOUS ENTRY
IMSPQL:	CAME A,1(Q)	;SKIP IF SAME LOCAL SOCKET NUMBER
	 JRST IMSPQ1	;TRY NEXT
	JUMPL T,IMSPQW	;WIN IF LISTENING SOCKET
	LDB W,[101000,,3(Q)]	;FOREIGN HOST IMPHTB INDEX
	CAMN W,H	;SKIP IF WRONG FOREIGN HOST
	 CAME B,2(Q)	;SKIP IF FOREIGN SOCKET NUMBER AGREES
	  JRST IMSPQ1	;TRY NEXT
IMSPQW:	SKIPGE W,(Q)	;FOUND IT
	 MOVEM J,IMPEPQ	;PATCH OUT OF THE QUEUE
	SKIPGE J
	 MOVEI J,IMPBPQ
	MOVEM W,(J)
	MOVE W,IMFFPQ	;ADD TO FREE LIST
	MOVEM W,(Q)
	MOVEM Q,IMFFPQ
	JRST POPJ1

IMSPQ1:	MOVE J,Q	;PREVIOUS ENTRY
	SKIPL Q,(Q)	;NEXT ENTRY
	 JRST IMSPQL	;LOOP
	POPJ P,		;NOT FOUND

SUBTTL	ARPANET CLOCK LEVEL

OVHMTR IMP	;NETWORK INTERRUPT LEVEL (NOT STYNET STUFF)

;HERE TO TIME OUT THE RFC QUEUE
IMFCT1:	CONO PI,NETOFF
	SKIPGE Q,IMPBPQ
	 JRST NETONJ	;... IF QUEUE IS EMPTY
	MOVNI J,1	;J HAS PTR TO PREV ELT OF LIST, FOR IMSPQW TO PATCH (DELQ).
IMFCT2:	LDB E,[221100,,3(Q)]	;TIME IN 16/15'THS, MOD 512., THAT RFC WAS RECEIVED
	LDB TT,[051100,,TIME]	;TIME, IN SAME UNITS, NOW.
	CAMLE E,TT		;MAKE SURE THE SUB TT,E GIVES A POSITIVE ANSWER.
	 ADDI TT,1_9		;WE ASSUME THAT TIME >= TIME OF RECEIPT.
	SUB TT,E
	CAIGE TT,IMFCTO_<-5>
	 JRST IMFCT3		;THIS RFC HASN'T TIMED OUT - LOOK AT NEXT
	PUSHJ P,IMSPQW		;IT HAS - FLUSH IT
	 JFCL
	JRST IMFCT1		;AND START AGAIN LOOKING FOR RFC'S TO FLUSH

IMFCT3:	MOVE J,Q
	SKIPL Q,(Q)
	 JRST IMFCT2
	JRST NETONJ	;END OF QUEUE

;FLUSH CLOSED NETWORK CHANNELS (CALLED AT HALF SEC CLOCK)
IMPCCL:	MOVSI I,-IMPSTL
IMPCCR:	CONO PI,NETON
	MOVSI T,200000
IMPCCZ:	TDNN T,IMSOC1(I)	;LOOK FOR CHANNELS NO LONGER OPEN.
	 AOBJN I,IMPCCZ
	JUMPL I,IMPCCA
	POPJ P,

IMPCCA:	CONO PI,NETOFF
	MOVE B,IMSOC6(I)
	TLNE B,600000	;ACTIVE AT PI LEVEL OR LOCKED BY CORE JOB
	 JRST IMPCCS
	HRRZ B,IMSOC4(I) ;DISPATCH ON SOCKET STATE.
	JRST @IMPCCT(B)

IMPCCT:	OFFSET -.
%NSCLS::IMPCC1
%NSLSN::IMPCC1
%NSRFC::IMPCC2
%NSRCL::IMPCC1
%NSRFS::IMPCC2
%NSOPN::IMPCC5
%NSRFN::IMPCC6
%NSCLW::IMPCC7
%NSCLI::IMPCC1
%NSINP::IMPCC2
	OFFSET 0

;IMP BUFFER RETURN
IMPBRT:	SKIPN IMSOC6(I)
	 POPJ P,	;NO BUF??
	LDB A,[221000,,IMSOC6(I)]
	CAIE A,377
	 JRST IMBRT1
	LDB A,[121000,,IMSOC6(I)]
	PUSHJ P,IMEMR
	CAIA
IMBRT1:	 PUSHJ P,IBRTN
	SETZM IMSOC6(I)
	POPJ P,

IMPCC1:	PUSHJ P,IMPBRT
	MOVSI A,20000
	TDNE A,IMSOC5(I)
	 JSP T,IMPC5D	;WAITING FOR FINAL RFNM
	SETZM IMSOC1(I)
	SOS IMNCS	;WE HAVE FINISHED CLOSING ONE SOCKET
IMPCCS:	AOBJN I,IMPCCR	;WE CLOSED ONE, OR GAVE UP ON ONE; LOOK AT NEXT
	JRST NETONJ	;OR WE'RE FINISHED LOOKING AT ALL.

IMPCC2:	PUSHJ P,IMPBRT
	SKIPLE T,IMFCQL
	 CAIG T,2	;SKIP IF MORE THAN 2 FREE
	  JRST IMPCCS	;NOT ENUF PI CONTROL QUEUE BLOCKS AVAIL
	LDB A,IMSCFH	;GET HOST#
	SKIPGE IMPHTB(A)	;SKIP IF NO RFNM WAIT ON LINK 0
	 JRST IMPCCS	;NOT NOW!
	PUSH P,IMPCSH
	MOVEM A,IMPCSH
	JSP T,IMSTCM
	    12.,,3	;12. BYTES, 3 WORDS
	 JRST 4,.	;NO SLOTS AVAIL.  CHECKED BEFORE
	MOVEI H,3_4	;3 NOPS + CLS
	MOVEM H,10(Q)
	MOVE H,IMSOC2(I)	;LOCAL SOCKET
	LSH H,4		;MOVE INTO 32 BIT FIELD
	MOVEM H,11(Q)
	MOVE H,IMSOC3(I)	;FOREIGN SOCKET
	LSH H,4
	MOVEM H,12(Q)
	PUSHJ P,IMWCQ	;SEND CLS
	POP P,IMPCSH
	MOVEI H,%NSCLW
	HRRM H,IMSOC4(I)
	MOVE H,TIME
	MOVEM H,IMSOCT(I)	;TIME CLS SENT
	JRST IMPCCS

IMPCC5:	MOVE H,IMSOC2(I)
	TRNN H,1	;SKIP IF SEND SOCKET
	 JRST IMPC5B	;RECEIVE SOCKET
	MOVE A,IMSPIP(I)
	CAMN A,IMSMPP(I) ;IS THERE STILL DATA TO SEND? AT MP LEVEL
	 CAMN I,IMPOPI	;OR PI LEVEL? OR RFNM WAIT?
IMPCC6:	  JSP T,IMPC5D	;YES, SEND IT AND GET RFNM BEFORE SENDING CLS
IMPC5B:	MOVEI H,%NSRFS	;NO, OK TO SEND A CLS NOW.
	HRRM H,IMSOC4(I);SET STATE SO WILL LOOP BACK TO IMPCC2
	JRST @IMPCCT(H)

IMPC5A:	IORM H,IMSOC5(I)
	MOVE H,TIME
	MOVEM H,IMSOCT(I)
	JRST IMPCCS

IMPC5D:	MOVSI H,10000
	TDNN H,IMSOC5(I)
	 JRST IMPC5A	;TIME-OUT NOT ALREADY STARTED - START IT.
IMPC7A:	MOVE H,TIME	;ALREADY STARTED, OVER YET?
	SUB H,IMSOCT(I)
	CAIG H,IMPCTO	;SKIP IF TIMED OUT
	 JRST IMPCCS	;NOT YET
	JRST (T)

IMPCC7:	JSP T,IMPC7A	;IF CLOSE TIME-OUT ISN'T UP, GIVE UP TO IMPCCS.
	JRST IMPCC1	;ELSE FLUSH.

;HERE FROM 1/2 SECOND CLOCK IF IMNAS IS NON-ZERO.
;WE WAKE UP ANY STYNET CHANNELS THAT NEED IT.
IMPAAA:	SOS IMNAS	;DECREASE NEED-THIS-ROUTINE COUNT
	MOVSI I,-IMPSTL
IMPAA1:	MOVSI T,200000
	TDNN T,IMSOC5(I)
	 AOBJN I,.-1
	JUMPGE I,CPOPJ
	CONO PI,NETOFF
	ANDCAM T,IMSOC5(I)
	PUSHJ P,IMPUIN
	CONO PI,NETON
	JRST IMPAA1

SUBTTL	ARPANET NCP INPUT INTERRUPT LEVEL

;GET HERE PI IN PROG ON NETCHN
;IMP HAS NETCHN PIA, TT HAS CONI WORD, A HAS LAST WD OF CONTROL LINK MSG
;PROCESS THE CONTROL LINK HOST-HOST PROTOCOL OPCODES.
IMPBK3:	AOS B,IMBLKI	;STORE LAST WORD AS IF BLKI HAD
	MOVEM A,(B)
	MOVEI B,-IMPINB+1(B)	;B HAS NUMBER OF WORDS READ
	CAMGE B,IMPNIW
	 JRST IMPCIS	;MESSAGE IS SHORT
	MOVE A,IMPCBC	;NUMBER OF BYTES
	MOVE B,[441000,,IMPINB]	;8 BIT BYTE POINTER TO MESSAGE
	SETZM IMPNEA
	SETZM IMPNRA
IMPBKL:	SOJL A,IMPIR1	;LOOP HERE TO PROCESS CONTROL MESSAGE
	MOVE H,IMPCSH	;RESTORE HOST INDEX
	ILDB C,B
	CAIL C,IMPCDL
	 JRST IMPCIG	;ILLEGAL OPCODE
	AOS IMPCMR(C)	;COUNT CTL MSG RCD
	JRST @IMPCDT(C)	;DISPATCH ON OPCODE

IMPCIG:	BUG INFO,[NET: NEW CTL MSG FM HST ],OCT,IMPHTN(H),[COD=],OCT,C,[CT=],OCT,A
	JRST IMPIR1

IMPCIS:	MOVE H,IMPCSH
	BUG INFO,[NET: SHORT CTL MSG FM HST ],OCT,IMPHTN(H)
	AOS IMNSCM
	JRST IMPIR1

IMPCDT:	IMPBKL	;NOP	( 0)
	IMPRFC	;RTS	( 1)
	IMPRFC	;STR	( 2)
	IMPCLS	;CLS	( 3)
	IMPALL	;ALL	( 4)
	IMPCIG	;GVB	( 5)
	IMPCIG	;RET	( 6)
	IMPINR	;INR	( 7)
	IMPINS	;INS	(10)
	IMPECO	;ECO	(11)
	IMPCIG	;ERP	(12)
	IMPERM	;ERR	(13)
	IMPRST	;RST	(14)
	IMPRRP	;RRP	(15)
	IMPCIG	;RAR	(16)
	IMPCIG	;RAS	(17)
	IMPCIG	;RAP	(20)
	IMPNXR	;NXR	(21)
	IMPNXR	;NXS	(22)
IMPCDL==.-IMPCDT

IMSHRT:	MOVNS A
	BUG INFO,[NET: SHORT CTL MSG HST ],OCT,IMPHTN(H),[COD=],OCT,C,[MISSING],OCT,A
	JRST IMPIR1

IMPNXR:	ILDB C,B	;LINK NUMBER FOR NXR OR NXS
	SOJA A,IMPBKL	;JUST IGNORE IT, USELESS ANYWAY

;RFC RECEIVED  C HAS OPCODE
IMPRFC:	SUBI A,9	;MUST BE AT LEAST 9 MORE BYTES
	JUMPL A,IMSHRT	;MESSAGE IS SHORT
	ILDB D,B	;D GETS 32 BIT FOREIGN SOCKET NUMBER
REPEAT 3,[
	LSH D,8
	ILDB T,B
	IORI D,(T)
]
	ILDB E,B	;E GETS 32 BIT LOCAL SOCKET NUMBER
REPEAT 3,[
	LSH E,8
	ILDB T,B
	IORI E,(T)
]
	ILDB R,B	;LINK NUMBER OR BYTE SIZE
	MOVE Q,E
	EQVI Q,(C)	;Q 1.1 = 1 IF E 1.1 = C 1.1
	ANDI Q,1
	JUMPE Q,IMPRF3	;WRONG DIRECTION RFC
	CAIE C,2	;SKIP IF STR
	 JRST IMPRF5
	CAILE R,36.	;SKIP IF STR AND BYTE SIZE < 37
	 JRST IMREFU	;REFUSE CONNECTION
IMPRF5:	PUSHJ P,IMPLLS	;LOOK FOR LOCAL SOCKET (RET INDEX IN I)
	 JRST IMPRFQ	;NO SUCH SOCKET.  QUEUE IT
	HRRZ W,IMSOC4(I)	;SOCKET STATE
	CAIE W,%NSLSN	;SKIP IF LISTENING
	 JRST IMPRF4
	MOVEM D,IMSOC3(I)	;STORE FOREIGN SOCKET NUMBER
	DPB H,IMSCFH		;STORE FOREIGN HOST INDEX
	MOVEI Q,%NSRFC
	HRRM Q,IMSOC4(I)	;RFC RECEIVED STATE
	CAIN C,2	;SKIP IF RTS
	 JRST [	LDB Q,IMSCBS	;STR, CHECK CONNECTION BYTE SIZE
		CAME Q,R
		 JRST IMCLDA
		JRST .+2 ]
	  DPB R,IMSCLN	;RTS, STORE LINK #
	PUSHJ P,IMPUIN	;INTERRUPT USER
IMRFCX:	LDB Q,IMHSBT
	CAIN Q,1
	 SOS IMRFCT
	MOVEI Q,2
	DPB Q,IMHSBT	;MARK HOST UP
	JRST IMPBKL

IMPRF3:	BUG INFO,[NET: WRONG DIR RFC HST ],OCT,IMPHTN(H),[OP ],SIXBIT,[(C)[SIXBIT /RTS   STR/]-1],[SOK],OCT,E
	JRST IMPBKL

IMPRF4:	CAIE W,%NSRFS	;SKIP IF IN RFC SENT STATE
	 JRST IMPRFQ	;QUEUE IT
	LDB Q,IMSCFH
	CAMN Q,IMPCSH
	 CAME D,IMSOC3(I)	;FROM CORRECT FOREIGN SOCKET?
	  JRST IMREFU	;NO, REFUSE
	AOS IMSOC4(I)	;PUT INTO STATE 5 - OPEN
	CAIE C,1	;SKIP IF RTS
	 JRST IMPRF2	;STR
	DPB R,IMSCLN	;STORE LINK #
IMPRF1:	PUSHJ P,IMPUIN	;INTERRUPT USER
	JRST IMPBKL

IMPRF2:	LDB Q,IMSCBS
	CAME Q,R
	 JRST IMCLDA	;BYTE SIZES DIFFER, REFUSE
	JSP T,IMSTCM
	    8,,2	;TEXT: 8 BYTES, 2 WORDS
	 JRST [	AOS IMNANS
		JRST IMPRF1 ]
	MOVEI H,2(I)
	LSH H,16.	;LINK #
	IOR H,IMSOC8(I) ;MSG ALLOC
	LSH H,4
	TLO H,(4_28.)	;ALL
	MOVEM H,10(Q)
	MOVE H,IMSOC7(I) ;BIT ALLOC
	LSH H,4
	MOVEM H,11(Q)
	PUSHJ P,IMWCQ	;SEND IT OUT
	JRST IMPRF1

IMPRFQ:	CAIL E,NETSRS	;IF < 1000, START JOB "NETRFC"
	 JRST IMRFQ5
	MOVE T,IMPHTN(H)
;	CAIE T,<IMPUS_-6>+<IMPUS&77>_9
	CAME T,[IMPUS3-NW%ARP]	; Compare with our own host (minus net #)
	 SKIPL NETUSW
	  CAIA
	   JRST IMREFU	;REFUSE CONNECTION
	HRROI T,NTRFCL
	PUSHJ P,NUJBST	;LOAD SERVER
	 JRST IMREFU	;RING BUFFER FULL
IMRFQ5:	SKIPGE Q,IMFFPQ	;SKIP IF ANY FREE SLOTS
	 JRST IMRFQ1	;CLS OLDEST
	MOVE W,(Q)
	MOVEM W,IMFFPQ	;NEW FIRST FREE
IMRFQ9:	SETOM (Q)	;END OF QUEUE
	MOVEM E,1(Q)	;LOCAL SOCKET NUMBER
	MOVEM D,2(Q)	;FOREIGN SOCKET NUMBER
	CAIE C,2	;SKIP IF STR
	 TLO R,400000	;MARK AS RTS
	MOVEM R,3(Q)	;LINK NUMBER OR BYTE SIZE
	DPB H,[101000,,3(Q)]	;FOREIGN HOST INDEX
	LDB W,[051100,,TIME]	;STORE TIME OF RECEIPT, IN 16/15 MOD 512.
	DPB W,[221100,,3(Q)]
	SKIPGE W,IMPEPQ	;END OF QUEUE
	 JRST IMRFQ2	;QUEUE EMPTY
	MOVEM Q,(W)	;PUT IN AT END OF QUEUE
	MOVEM Q,IMPEPQ	;NEW END OF QUEUE
	JRST IMRFCX

IMRFQ2:	MOVEM Q,IMPEPQ	;END OF QUEUE
	MOVEM Q,IMPBPQ	;AND BEGINNING OF QUEUE
	JRST IMRFCX

IMRFQ1:	MOVE J,IMPBPQ	;BEGINNING OF PENDING QUEUE
	MOVE E,1(J)	;LOCAL SOCKET
	MOVE D,2(J)	;FOREIGN SOCKET
	PUSH P,IMPCSH
	LDB H,[101000,,3(J)]	;FOREIGN HOST INDEX
	MOVEM H,IMPCSH
	PUSHJ P,IMPSCL	;SEND CLS
	 JRST IMRFQ3	;NO BUFFERS AVAILABLE
	AOSA IMNRFC	;# RFCS CLOSED
IMRFQ3:	 AOS IMNRFI	;# RFCS IGNORED
	POP P,IMPCSH
	MOVE H,IMPCSH
	MOVE Q,IMPBPQ	;FLUSH FIRST ENTRY ON PENDING QUEUE
	MOVE W,(Q)
	MOVEM W,IMPBPQ
	JRST IMRFQ9

IMREFU:	PUSHJ P,IMPSCL	;SEND CLS
	 AOS IMNCNS	;CAN'T
	AOS IMNRFI
	JRST IMPBKL

IMPCLS:	SUBI A,8	;MUST BE AT LEAST 8 MORE BYTES
	JUMPL A,IMSHRT	;MESSAGE IS SHORT
	ILDB D,B	;D GETS 32 BIT FOREIGN SOCKET NUMBER
REPEAT 3,[
	LSH D,8
	ILDB T,B
	IORI D,(T)
]
	ILDB E,B	;E GETS 32 BIT LOCAL SOCKET NUMBER
REPEAT 3,[
	LSH E,8
	ILDB T,B
	IORI E,(T)
]
	PUSHJ P,IMPLC	;LOOK FOR CONNECTION
	 JRST IMCLSQ	;LOOK IN QUEUE
	MOVSI W,200000	;SET CLS RCD BIT
	IORB W,IMSOC4(I)	;RH IS STATE FOR DISPATCH
	JRST @IMCLDT(W)

IMCLDT:	OFFSET -.
%NSCLS::IMPCLI
%NSLSN::IMPCLI
%NSRFC::IM2CLS
%NSRCL::IMPCLI
%NSRFS::IM4CLS
%NSOPN::IM5CLS
%NSRFN::IM6CLS
%NSCLW::IM7CLS
%NSCLI::IMPCLI
%NSINP::IMECLS
	OFFSET 0

IM4CLS:	HLLZS IMSOC4(I)	.SEE %NSCLS
	MOVEI W,%NCRFS
	JRST IMCLDB

IMECLS:	MOVEI W,%NSCLI
	JRST IMCCLS

IMCLDA:	HLLZS IMSOC4(I)	.SEE %NSCLS
	MOVEI W,%NCBYT	;BYTE MISMATCH
	JRST IMCLDB

IM6CLS:	MOVSI W,20000	;CLSED DURING RFNM WAIT
	IORM W,IMSOC5(I)
IM5CLS:	TDZA W,W	.SEE %NSCLS
IM2CLS:	 MOVEI W,%NSRCL
IMCCLS:	HRRM W,IMSOC4(I)	;CHANGE STATE
	MOVEI W,%NCFRN
IMCLDB:	DPB W,IMSCLS	;CLS REASON
	PUSHJ P,IMPUIN	;INTERRUPT USER
IMCLQ2:	PUSHJ P,IMPSCL	;SEND CLS
	 AOS IMNCNS
	JRST IMPBKL

IMPSCL:	JSP T,IMSTCM	;SEND A CLS TO LOCAL SOCKET IN E AND FOREIGN SOCKET IN D (CLOBBERS D AND E)
	    12.,,3	;TEXT: 12 BYTES, 3 WORDS
	 POPJ P,
	MOVEI H,3_4	;3 NOPS + CLS
	MOVEM H,10(Q)
	LSH E,4
	MOVEM E,11(Q)	;LOCAL SOCKET NUMBER
	LSH D,4
	MOVEM D,12(Q)	;FOREIGN SOCKET NUMBER
	PUSHJ P,IMWCQ	;SEND CLS
	JRST POPJ1

IMPCLI:	AOS IMNCLI
	JRST IMPBKL

IM7CLS:	HLLZS IMSOC4(I)	.SEE %NSCLS
	JRST IMPBKL

IMCLSQ:	PUSH P,A
	PUSH P,B
	MOVE A,E	;LOCAL SOCKET NUMBER
	MOVEI T,0
	MOVE B,D	;FOREIGN SOCKET NUMBER
	PUSHJ P,IMSPQP	;SEARCH PENDING QUEUE
	 JRST IMCLQ1	;NOT THERE
	MOVE E,A
	POP P,B
	POP P,A
	JRST IMCLQ2	;SEND HIM A CLS

IMCLQ1:	POP P,B
	POP P,A
	JRST IMPCLI	;CAN'T FIND HIM.  IGNORE

IMPALL:	SUBI A,7	;MUST BE AT LEAST 7 MORE BYTES
	JUMPL A,IMSHRT	;MESSAGE IS SHORT
	ILDB R,B	;LINK #
	ILDB D,B
	LSH D,8
	ILDB T,B
	IORI D,(T)	;D GETS MESSAGE ALLOCATION
	ILDB E,B	;E GETS BIT ALLOCATION
REPEAT 3,[
	LSH E,8
	ILDB T,B
	IORI E,(T)
]
	MOVE T,IMPCSH	;FOREIGN HOST
	LSH T,8
	IOR R,T		;HEADER (HOST AND LINK #)
	MOVEI W,1	;TO TEST DIRECTION OF SOCKET
	MOVSI I,-IMPSTL
IMPAL2:	LDB T,IMSCHD	;FOREIGN HOST AND LINK NUMBER
	SKIPGE IMSOC1(I)	;SKIP IF SLOT NOT IN USE
	 CAME T,R	;SKIP IF HEADER AGREES
	  JRST IMPAL1
	TDNE W,IMSOC2(I)	;SKIP IF NOT SEND
	 JRST IMPAL3
IMPAL1:	AOBJN I,IMPAL2
	ANDI R,377
	BUG INFO,[NET: IGNORED ALLOC HST ],OCT,IMPHTN(H),[LNK],OCT,R
	AOS IMNALI
	JRST IMPBKL	;IGNORE

IMPAL3:	SKIPL D
	 SKIPGE E
	  JRST 4,.
	LDB T,IMSCBS		;GET BYTESIZE
	IDIV E,T		;TRUNCATE TO 0 MODULO BYTESIZE
	IMUL E,T		;(CLOBBER TT)
	SKIPL IMSOC8(I)
	 SKIPGE IMSOC7(I)
	  JRST 4,.
	ADDB D,IMSOC8(I)	;INCREASE ALLOCATIONS
	ADDB E,IMSOC7(I)
	MOVE Q,IMSOC5(I)
	TLNE Q,140000		;ACTIVATE IF USER (OR DIRECT CONN) CHECKING ALLOC
	 PUSHJ P,IMPUIN
	MOVE T,IMSPIP(I)
	CAME T,IMSMPP(I)	;SKIP IF OUTPUT BUFFER EMPTY
	 PUSHJ P,IMPIOS		;THIS GUY MAY HAVE STUFF TO GO OUT
	JRST IMPBKL

IMPLLS:	MOVSI I,-IMPSTL	;LOOK FOR SOCKET IN E
	MOVSI W,200000
IMPLL2:	TDNN W,IMSOC1(I)
	 SKIPL IMSOC1(I)	;NOT IN USE
	  JRST IMPLL1
	CAME E,IMSOC2(I)	;SKIP IF RIGHT LOCAL SOCKET NUMBER
IMPLL1:	 AOBJN I,IMPLL2
	JUMPL I,POPJ1	;RETURN SOCKET TABLE INDEX IN RH OF I
	POPJ P,		;NOT FOUND

;INTERRUPT USER ASSOCIATED WITH CHANNEL IN I
IMPUIN:	MOVSI U,200000
	TDNE U,IMSOC1(I)
	 POPJ P,		;CHNL BEING CLOSED
	MOVE U,IMSOC5(I)
	TLNE U,40000
	 JRST IMPUIS		;JUMP IF SOCKET IS CONNECTED TO A STY.
IMPUIP:	HRRZ U,IMSOC1(I)	;USER INDEX
	LDB Q,[222000,,IMSOC1(I)]	;MASK FOR CHANNEL OPEN ON
IMPUIM:	AND Q,MSKST2(U)		;ONLY ENABLED CHANNELS.
	PUSH P,T		;VALIDATE THE USER INDEX
	MOVEI T,LUBLK
	IDIVM U,T
	IMULI T,LUBLK
	CAMN T,U
	 CAML U,USRHI
	  JRST 4,.
	MOVSI T,(SETZ)		;PCLSR SO IT GETS IOC ERROR IF NEEDFUL
	IORM T,PIRQC(U)		; EVEN IF IT DOESN'T HAVE NORMAL INTERRUPTS ENABLED
	POP P,T
	IORM Q,IFPIR(U)		;GEN SECOND WORD INTERRUPT
	POPJ P,

IMPUIS:	PI2SAF			;HERE FOR INT. ON SOCKET CONNECTED TO A STY:
	ANDI U,777
	SKIPL STYNTL-NFSTTY(U)
	 POPJ P,		;ALREADY ACTIVATED
	MOVE Q,STYNTA		;PUT THAT STY ON THE XFER ACTIVATION LIST.
	MOVEM Q,STYNTL-NFSTTY(U)
	MOVEM U,STYNTA		;THEN RETURN.  DON'T ACTUALLY INTERRUPT THE JOB;
	POPJ P,			;IF ANYTHING FUNNY HAS HAPPENED, STYNTC WILL INTERRUPT.

;LOOK FOR CONNECTION: LOCAL SOCKET IN E, FOREIGN SOCKET IN D, FOREIGN HOST IN H
IMPLC:	MOVSI I,-IMPSTL
IMPLC2:	SKIPGE IMSOC1(I)	;NOT IN USE
	 CAME E,IMSOC2(I)	;LOCAL SOCKET NUMBER
	  JRST IMPLC1
	LDB T,IMSCFH
	CAMN D,IMSOC3(I)	;FOREIGN SOCKET NUMBER
	 CAME H,T
IMPLC1:	  AOBJN I,IMPLC2
	JUMPL I,POPJ1
	POPJ P,

IMPINR:	SOJL A,IMSHRT	;SHORT COUNT
	ILDB D,B	;LINK #
	DPB H,[101000,,D] ;CONCAT HOST&LINK
	MOVSI I,-IMPSTL
	LDB E,IMSCHD	;GET HOST FOR SOCKET
	CAME D,E
	 AOBJN I,.-2	;SEARCH FOR MATCHING HOST&LINK
	JUMPGE I,IMPILS	;NOT FOUND
NCPIRS:	HRRZ E,IMSOC4(I)	;STATE
	MOVE E,CHNBIT(E)	;BIT TO CORRESPOND
	TRNN E,1_%NSRFC+1_%NSRFS+1_%NSOPN+1_%NSRFN+1_%NSCLW+1_%NSINP
			;OK STATES RFCRCV, RFCSNT, OPEN, RNMWT, CLSSNT, DATA
	 JRST IMPILS	;IN BAD STATE
	TRNE E,1_%NSCLW	;IGNORE INT IF CLSSNT STATE (NOT ERROR)
	 JRST IMPBKL
	MOVSI D,4000
	IORM D,IMSOC5(I)	;INT FLAG 4.3 BIT OF IMSOC5(SOCK)
	PUSHJ P,IMPUIN	;INT TO USER
	JRST IMPBKL

IMPINS:	SOJL A,IMSHRT	;SHORT
	ILDB D,B	;LINK
	MOVEI I,-2(D)	;0,1 -> 777776,777777 ILLEGAL LINKS
	CAIGE I,IMPSTL	;CHECK IN RANGE 2 TO IMPSTL+1
	 SKIPL IMSOC1(I);AND IN USE
	  JRST IMPILS	;BAD LINK
	LDB T,IMSCFH
	CAMN T,IMPCSH	;SKIP IF HOST NOT MATCHED BY MSG
	 JRST NCPIRS
IMPILS:	BUG INFO,[NET: BAD INT CTL MSG HST ],OCT,IMPHTN(H),[LNK ],OCT,D,[IMSOC4],OCT,IMSOC4(I)
	JRST IMPBKL	;NOTE- I MAY BE -1 OR -2  OR UP TO 256, IF LNK BAD, IGNORE

IMPECI:	AOS IMPNEI	;WILL EVENTUALLY GIVE JOB TO MAIN PROG
	JRST IMPBKL

IMPECO:	ILDB D,B	;GET 8 BIT DATA TO ECHO
	SOJL A,IMSHRT
	SKIPE IMPNEA
	 JRST IMPECI	;ONLY ONE TO A CUSTOMER
	JSP T,IMSTCM
	    2,,1	;TEXT: 2 BYTES, 1 WORD
	 JRST IMPECI
	LSH D,20.	;DATA TO BE ECHOED
	TLO D,(10._28.)	;ERP
	MOVEM D,10(Q)
	PUSHJ P,IMWCQ	;SEND IT OUT
	AOS IMPNEA
	JRST IMPBKL

IMPERM:	SUBI A,11.	;COUNT BYTES
	MOVE C,TIME
	MOVEM C,IMPERB
	MOVE C,IMPHTN(H)	;REAL HOST NUMBER
	MOVEM C,IMPERB+1
	MOVE C,[441100,,IMPERB+2]
	MOVEI D,11.	;BYTES TO COPY
	ILDB T,B	;COPY BYTES FROM THEIR MSG
	IDPB T,C
	SOJG D,.-2
	BUG INFO,[NET: ERR MSG FM HST ],OCT,IMPERB+1,[MSG],OCT,IMPERB+2,OCT,IMPERB+3
			;ONLY PRINTS FIRST 8 BYTES OF ERR INFO
	JUMPGE A,IMPBKL	;IF COUNT OK, GET MORE
	JRST IMSHRT	;SHORT COUNT

IMPRSI:	AOS IMPNRI
	JRST IMPBKL

IMPRST:	MOVE T,IMPHTN(H)
;	CAIE T,<IMPUS_-6>+<IMPUS&77>_9	;IF RST FROM OURSELVES, JUST SEND RRP
	CAME T,[IMPUS3-NW%ARP]
	 PUSHJ P,IMPRSR
	SKIPE IMPNRA
	 JRST IMPRSI
	JSP T,IMSTCM
	    1,,1	;TEXT: 1 BYTE, 1 WORD
	 JRST IMPRSI
	MOVSI D,(13._28.)	;RRP
	MOVEM D,10(Q)
	PUSHJ P,IMWCQ	;SEND IT OUT
	PUSHJ P,IMPIOS
	AOS IMPNRA
	JRST IMPBKL

IMPRSR:	MOVSI I,-IMPSTL	;LOOK FOR USERS OF THIS HOST
	MOVSI TT,200000
IMPRS2:	TDNN TT,IMSOC1(I)	;GUY GOING AWAY ANYHOW
	 SKIPL IMSOC1(I)
	  JRST IMPRS1
	LDB C,IMSCFH	;FOREIGN HOST
	CAME C,IMPCSH
	 JRST IMPRS1	;WRONG HOST
	HRRZ C,IMSOC4(I)
	MOVEI D,%NSCLS
	CAIN C,%NSINP
	 MOVEI D,%NSCLI	;INPUT STILL AVAILABLE
	HRRM D,IMSOC4(I)
	MOVEI D,%NCRST
	DPB D,IMSCLS	;CLS REASON IS RST
	PUSHJ P,IMPUIN	;INTERRUPT USER
IMPRS1:	AOBJN I,IMPRS2
	;IF HOST CAN SEND A RST, IT IS UP, BUT DON'T
	;REALLY CONSIDER IT UP UNTIL RRP, RTS, OR STR IS RECEIVED
	;I DON'T KNOW WHY IT'S DONE THIS WAY
	POPJ P,

IMPRRP:	LDB J,IMHSBT
	SOJL J,IMPRR1
	JUMPG J,IMPBKL	;ALREADY UP, MAYBE BECAUSE OF PRIOR RTS,STR
	MOVEI J,2
	DPB J,IMHSBT	;MARK HIM UP
	SOS IMRFCT
	JRST IMPBKL

IMPRR1:	BUG INFO,[NET: RRP W-O RST HST],OCT,IMPHTN(H)
	JRST IMPBKL

;GET CONTROL QUEUE SLOT
IMGCQS:	SKIPG IMFCQL	;SKIP IF ANY LEFT
	 JRST IMGCQL	;NONE
	SKIPG Q,IMFFCQ	;POINTER TO SLOT
	 JRST 4,.
	MOVE W,(Q)
	MOVEM W,IMFFCQ	;PATCH OUT OF FREE LIST
	SETOM (Q)
	SOS W,IMFCQL	;NUMBER FREE LEFT
	CAIN W,1	;SKIP IF MORE THAN ONE LEFT
	 SETOM IMPHI	;SET FLAG TO HOLD UP INPUT
	JRST POPJ1

IMGCQL:	AOS IMNPIL
	POPJ P,

IMWCQ:	PUSHJ P,IMWPCQ
	JRST IMPIOS	;START OUTPUT

;ADD BLOCK IN Q TO OUTPUT CONTROL QUEUE, BASHES W
IMWPCQ:	SETOM (Q)
	SKIPGE W,IMPLCQ
	 JRST IMWCQ1	;CONTROL QUEUE EMPTY
	AOSE (W)
	 JRST 4,.	;END OF QUEUE DIDN'T POINT TO -1
	MOVEM Q,(W)
	MOVEM Q,IMPLCQ
	POPJ P,

IMWCQ1:	MOVEM Q,IMPLCQ
	MOVEM Q,IMPNCQ
	POPJ P,

;ADD MAIN PROGRAM BLOCK TO PI QUEUE (CALL AT MP LEVEL)
IMPMPQ:	MOVSI Q,777
	IORM Q,IMPMPU+1	;NOT LOCKED BY THIS JOB ANY MORE
	SKIPL U		;SKIP IF CALLED FROM DIRECT-CONNECT CLOCK LEVEL
	 PUSHJ P,LSWDEL	;PI LEVEL WILL UNLOCK
	CONO PI,NETOFF
	MOVEI Q,IMPMPL
	PUSHJ P,IMWPCQ
	CONO PI,NETON
	JRST IMPOST

;CALL BY JSP T,IMSTCM
;SET UP STANDARD PI CONTROL MESSAGE
;BYTE COUNT,,TEXT LENGTH 
;ERROR RETURN

IMSTCM:	PUSHJ P,IMGCQS	;GET CONTROL QUEUE SLOT IN Q
	 JRST 1(T)	;NONE AVAILABLE
	MOVSI H,17_10.	;MESSAGE TYPE = 0, LINK # = 0, NEW FMT
	MOVEM H,2(Q)
	MOVE H,IMPCSH	;GET IMP AND HOST
	MOVE H,IMPHTN(H)
IFN 1,	DPB H,[103000,,3(Q)]	; Store host addr
IFN 0,[	DPB H,[301000,,3(Q)] ;STORE HOST
	LSH H,-9
	DPB H,[102000,,3(Q)] ;STORE IMP
] ;IFN 0
	HLRZ H,(T)	;BYTE COUNT
	LSH H,8
	IOR H,[8_24.]	;BYTE SIZE = 8
	MOVEM H,7(Q)
	HRLZ H,(T)
	HRR H,IMPCSH
	MOVSM H,1(Q)	;HOST INDEX,,TEXT LENGTH
	JRST 2(T)	;NORMAL RETURN (NOTE THAT H HAS BEEN RESTORED TO IMPCSH)

;RECEIVED LEADER OF REGULAR MESSAGE NOT ON CONTROL LINK
;THE HOST-HOST LEADER WORD (WD 6) HAS NOT YET BEEN DATAI'ED.
;SWITCH TO 32-BIT MODE FIRST IF NECESSARY.
IMPRMD:	
IFN INETP,[
	CAIE B,IMPILB+4	; Verify that NCP leader is next word
	 JRST IMPLD3	; Barf...
]
	MOVE D,IMPCSH
	LSH D,8
	MOVE I,IMPCLN
	IOR D,I		;HEADER
	SUBI I,2	;SOCKET TABLE INDEX
	JUMPL I,IMPRM7	;BAD LINK #
	SKIPGE A,IMSOC1(I)
	 TLNE A,200000	;SKIP IF NOT BEING CLOSED
	  JRST IMPRM7	;SOCKET DOESNT EXIST OR BEING CLOSED
	MOVEI A,1
	CAIGE I,IMPSTL
	 TDNE A,IMSOC2(I)	;SKIP IF RECEIVER
	  JRST IMPRM7	;BAD LINK # OR MESSAGE FOR A SENDER
	LDB C,IMSCHD	;HEADER
	CAME D,C	;SEE IF HEADERS AGREE
	 JRST IMPRM7	;NOPE, I.E. FROM WRONG HOST OR CLOSED
	HRRZ D,IMSOC4(I)
	CAIE D,%NSOPN
	 CAIN D,%NSINP
	  JRST IMPRMA
	JRST IMPRM7
IMPRMA:	SKIPGE IMSOC6(I)	;SKIP IF NOT LOCKED BY CORE JOB
	 JRST IMPRMP		;LOCKED, COME BACK LATER
IFN KAIMP,[
	SKIPL IMSOC5(I)		;SKIP IF 32 BIT TRANSFER
	 CONO IMP,IMI32C	;SET 36 BIT INPUT
	SKIPGE IMSOC5(I)	;SKIP IF NOT 32 BIT TRANSFER
	 CONO IMP,IMI32S	;SET 32 BIT INPUT
]IFN DMIMP,[
	SKIPL IMSOC5(I)		;SKIP IF 32BIT
	 CONO FI,FII32C		;SET 36BIT
	SKIPGE IMSOC5(I)	;SKIP IF 36 BIT
	 CONO FI,FII32S		;SET 32 BIT
]
	DATAI IMP,IMPILB+5	;GET THE HEADER WORD
	LDB A,IMCBBP
	MOVEM A,IMPCBS
	LDB B,IMSCBS		;Check for fraudulent byte size
	CAME A,B
	 JRST IMPRMZ		;Discard message
	LDB B,IMBCBP
	MOVEM B,IMPCBC
	MOVEM B,IMPNBI		;SAVE BYTE COUNT FOR LATER
	SOSGE IMSOC8(I)
	 JRST IMRMAF		;MESSAGE ALLOCATION EXCEEDED
	JUMPE B,IMPIRT		;ZERO LENGTH MESSAGE
	IMUL A,B		;BIT COUNT
	MOVN D,A
	ADDB D,IMSOC7(I)	;REMAINING BIT ALLOCATION
	JUMPL D,IMRMAH		;BIT ALLOCATION EXCEEDED
	TRNE TT,IMPLW
	 JRST IMRMAG		;MESSAGE IS SHORT
	MOVSI D,200000
	IORB D,IMSOC6(I)	;ACTIVE AT PI LEVEL
	SKIPGE IMSOC5(I)
	 IDIVI A,32.
	SKIPL IMSOC5(I)
	 IDIVI A,36.
	SKIPE B
	 ADDI A,1		;NUMBER OF WORDS MESSAGE WILL TAKE
	HRRZ B,IMSPIP(I) 	;ADDRESS WHERE MESSAGE HEADER WILL GO
	SKIPL (B)
	 JRST 4,.		;HEADER WORD SHOULD BE -1
	HRRZ C,IMSBFE(I)	;GET ADDRESS OF LAST WORD IN BUFFER
	CAML B,C
	 MOVEI B,-1(D)		;HEADER IS LAST IN BUFFER, SO DATA IS FIRST
	MOVE E,B		;RH(BLKI POINTER) IN E
	ADD A,B			;ADDRESS WHERE LAST WORD OF MESSAGE WILL GET STORED
	SETZM IMNWSI		;ASSUME WILL ONLY NEED ONE BLKI
	CAMG A,C
	 JRST IMPRM8		;JUMP IF NO WRAP
;DROPS THROUGH
;DROPS IN
	SUB B,C			;- # WDS TO READ FIRST TIME
	SUB A,C			;+ # WDS TO READ SECOND TIME
	SKIPGE B
	 SKIPG A
	  JRST 4,.		;SCREW
	MOVN C,A		;NEG OF REMAINING WORD COUNT
	MOVSS C			;TO LEFT HALF FOR BLKI POINTER
	HRRI C,-1(D)		;RING AROUND TO BEGIN OF BUFFER
	MOVEM C,IMNWSI		;STORE FOR INTCHN BLKI RUNOUT (FLAG IF -)
	ADD C,A			;ADR+COUNT
	HRRZM C,IMPNIW		;EXPECTED END OF BLKI
	SKIPA A,B
IMPRM8:	 SUBM B,A		;A GETS - # WORDS TO READ
	MOVE B,E
	HRL B,A			;BLKI POINTER
	SUB E,A			;EXPECTED LAST WORD
	SKIPE IMNWSI		;IF DOING 2 BLKIS, EXPECTED END ALREADY STORED
	 SKIPA E,IMPNIW
	  MOVEM E,IMPNIW	;EXPECTED LAST BLKI ADDRESS
	HRRZ A,IMSPIP(I)	;SEE IF CLOBBERING GOOD-DATA PART OF BUFFER
	CAIL A,@IMSMPP(I)	;SKIP IF MPP > PIP
	 JRST [	CAIG E,(A)
		 CAIGE E,@IMSMPP(I)
		  JRST IMPRMT
		JRST 4,. ]
	CAIGE E,@IMSMPP(I)
	 CAIG E,(A)
	  JRST 4,.
IMPRMT:	HRRZ A,IMSOC6(I)	;SEE IF CLOBBERING CORE NOT PART OF BUFFER
	CAIL E,(A)
	 CAILE E,@IMSBFE(I)
	  JRST 4,.
	HRRZM I,IMPIPI		;THIS SOCKET NOW ACTIVE AT P.I. LEVEL
	MOVEI C,%ISIND		; New state = reading NCP data message
	JRST IMPRM9		; Start reading

IMPRMP:	MOVSI D,100000		;SET INPUT HELD UP BY CORE JOB
	IORM D,IMSOC6(I)
IFN KAIMP,[
	MOVE D,IMPPIA
	MOVEM D,IMPSVP
	SETZM IMPPIA	;TURN OFF NETWORK FOR A WHILE
]
IFN DMIMP,CONO FI,FIIN+0	;SET PIA TO 0 FOR A WHILE, CORE JOB WILL GET BACK
	JRST IMPRET

IMRMAH:	AOSA IMNBAE
IMRMAF:	 AOS IMNMAE
	JRST IMPIRT

IMPRM7:	AOSA IMNMNC
IMRMAG:	 AOS IMNMSS
	JRST IMPIRT

; Got Last Imp Word (in A) of regular NCP data message
; Comes here from IMPBKX.

IMPRMB:	MOVE I,IMPIPI
	MOVE B,IMBLKI
	CAMN B,IMPNIW
	 JRST IMPRMC	;ONE EXTRA WORD OF IMP PADDING, IGNORE IT
	ADD B,[1,,1]	;ADDR TO NEXT WORD, COUNT TO ZERO
	CAME B,IMPNIW
	 JRST IMPRMY
	MOVEM A,(B)	;STORE LAST WORD
IMPRMC:	MOVE E,IMPNBI		;# BYTES IN
	ADDM E,IMSMPC(I)	;MAKE AVAIL TO M.P.
	MOVEM E,@IMSPIP(I)	;STORE HEADER
	AOS E,IMPNIW		;WORD AFTER MSG WILL BE NEXT HEADER
	CAILE E,@IMSBFE(I)
	 HRRZ E,IMSOC6(I)	;WRAP
	HRRM E,IMSPIP(I)	;LEAVE LH OF IMSPIP ALONE
	CAIN E,@IMSMPP(I)
	 JRST 4,.		;BUFFER 1 WORD TOO SMALL?
	SETOM (E)
	MOVEI E,%NSINP
	HRRM E,IMSOC4(I)	;INPUT AVAILABLE
	PUSHJ P,IMPUIN		;INTERRUPT USER
	MOVSI D,200000		;CLEAR ACTIVE AT P.I. LEVEL
	ANDCAM D,IMSOC6(I)
	SETOM IMPIPI
	JRST IMPIR1

IMPRMY:	HRRZ E,IMPNIW		;NOT ENDING WHERE IT'S SUPPOSED TO
	SUBI E,(B)		;E GETS NUMBER OF MISSING WORDS
	MOVE H,IMPCSH
	BUG INFO,[NET: MSG FM HST ],OCT,IMPHTN(H),[SHORT ],DEC,E,[WDS, BC],DEC,IMPCBC
	JRST IMPRMC		;PRETEND HOST TRANSMITTING GARBAGE

IMPRMZ:	MOVE H,IMPCSH
	BUG INFO,[NET: HST ],OCT,IMPHTN(H),[SENT BYTE SIZE ],DEC,A,[SHOULD BE],DEC,B
	JRST IMPIRT		;Discard message

SUBTTL	ARPANET NCP OUTPUT INTERRUPT LEVEL

;HERE ON COMPLETION OF TRANSMISSION OF CONTROL MESSAGE

IMPOB6:	SETZM IMPOS
	SKIPN A,IMPSVQ
	 JRST IMPRET		;THAT WAS A NOP
	HLRZ B,1(A)		;HOST TABLE INDEX
	MOVSI D,400000
	IORM D,IMPHTB(B)	;SET RFNM WAIT BIT
	AOS IMRFCT
	LDB D,[051100,,TIME]
	DPB D,[221100,,IMPHTB(B)] ;STORE TIME TOO
	HLRZ T,A
	HRRZS A
	MOVE B,(A)
	MOVEM B,(T)
	JUMPGE B,IMOB7A
	CAME A,IMPLCQ
	 JRST 4,.	;IMPLCQ GAVE WRONG LAST MESS NO.
	MOVEM T,IMPLCQ
	CAIN T,IMPNCQ
	 SETOM IMPLCQ
IMOB7A:	CAIN A,IMPMPL	;SKIP IF NOT MAIN PROG BLOCK
	 JRST [	SETOM IMPMPU
		JRST IMPRET ]
	MOVE B,IMFFCQ
	CAIN B,(A)
	 JRST 4,.	;MAKING INFINITE LOOP
	MOVEM B,(A)
	MOVEM A,IMFFCQ
	AOS A,IMFCQL
	SKIPGE B,IMPHI	;RETURN IF INPUT NOT HELD UP
	 CAIG A,1	;SKIP IF INPUT HELD UP AND NOW ENOUGH FREE
	  JRST IMPRET
	SETZM IMPHI
	AOJE B,IMPRET	;INPUT WAS NOT YET SUCCESSFULLY HELD UP
	AOJN B,[JRST 4,.]	;IMPHI SHOULD HAVE BEEN -2
	AOS IMPNUH
	MOVE TT,IMSTAS	;GET OLD CONI
	TRNE TT,IMPLW
IFN KAIMP,[
	 CONO IMP,IMI32C
	DATAI IMP,A
];KAIMP
IFN DMIMP,[
	 CONO FI,FII32C
	MOVE A,IMPSUS
];DMIMP
	TRNE TT,IMPLW	;RESUME INPUT
	 JRST IMPBKV
	SKIPE IMPIS
	 JRST 4,.
	JRST IMSTRT

;HERE ON COMPLETION OF TRANSMISSION OF DATA MESSAGE

IMPOBG:	SETZM IMPOS
	MOVE I,IMPOPI
	HRRZ Q,IMSOC4(I)
	CAIN Q,%NSOPN
	 AOS IMSOC4(I) .SEE %NSRFN	;PUT INTO RFNM WAIT STATE
	MOVSI A,20000
	CAIN Q,%NSCLS
	 IORM A,IMSOC5(I)
	MOVSI Q,200000
	ANDCAB Q,IMSOC6(I)	;NO LONGER ACTIVE AT P.I. LEVEL
	SETOM IMPOPI
	MOVN A,IMPNBT		;BITS SENT
	ADDM A,IMSC7I(I)	;DECREASE BITS IN BUFFER
	ADDB A,IMSOC7(I)	;DECREASE ALLOCATION
	SKIPL A			;SKIP IF ALLOC LOST
	SOSGE IMSOC8(I)		;SKIP IF MSG ALLOC DIDN'T LOSE
	 JRST 4,.		;LOST
	MOVE Q,IMSOC5(I)
	TLNN Q,140000		;INTERRUPT USER IF DIRECT CONNECT (CHEAP), DEPEND ON ALLOC,
	 SKIPN IMSMPC(I)	; OR IF OUTPUT BUFFER WAS FULL,
	  PUSHJ P,IMPUIN	; SINCE HE MAY WANT TO SEND MORE
	MOVE A,IMPNBO		;# BYTES FREED IN BUFFER BY REMOVAL OF MSG
	ADDM A,IMSMPC(I)	;SPACE USED BY MESSAGE NOW FREE
	MOVE A,IMPNPT		;UPDATE IMSPIP
	HRRZ Q,IMSOC6(I)	;VALIDATE THIS
	CAILE Q,(A)
	 JRST 4,.		;POINTS BEFORE BUFFER
	HRRZ Q,IMSBFE(I)
	CAIGE Q,(A)
	 JRST 4,.		;POINTS AFTER BUFFER
	MOVEM A,IMSPIP(I)	;..
	JRST IMPRET

;OUTPUT A DATA MESSAGE.

IMPOBD:	MOVE T,TIME
	SUB T,IMSOCT(I)
	SKIPL IMSOC4(I)	;SKIP IF WANT TO SEND THIS BUFFER
	 CAIL T,30.*2	;SKIP IF BUFFER FIRST WRITTEN LESS THAN 2 SEC AGO
	  JRST IMOBD1
	JRST IMPOBA	;DON'T SEND NOW, GO BACK AND LOOK FOR OTHERS

IMOBD1:	MOVE TT,IMSPIP(I)
	CAMN TT,IMSMPP(I)	;SKIP IF ANY BITS TO SEND
	 JRST IMPOBA		;NO
	SKIPE IMSOC7(I)		;SKIP IF NO BITS ALLOCATED
	 SKIPN IMSOC8(I)	;SKIP IF MSG ALLOCATED
	  JRST IMPOBA		;NO BITS OR NO MSGS ALLOWED
	MOVSI Q,200000
	IORB Q,IMSOC6(I)	;ACTIVE AT PI LEVEL

;CODE TO SEND OUT A BUFFER OR PARTIAL BUFFER
;ON ENTRY - I/ SOCKET TABLE INDEX
;	    Q/ BUFFER POINTER FROM IMSOC6
;	   TT/ BYTE POINTER TO FIRST BYTE TO SEND
;SETS UP  - T/ WORD SIZE (32 OR 36)
;	    E/ FLAGS FROM IMSOC5
;	    B/ BYTE SIZE
;	    C/ # BITS TO SEND

	SETZM IMPNBO
	MOVE T,IMSMPP(I)
	MOVEM T,IMOB0Z		;SAVE FOR DEBUGGING
	MOVEI T,32.
	SKIPL E,IMSOC5(I)	;SKIP IF IN 32BIT MODE
	 MOVEI T,36.		;SET 36BIT
	LDB B,IMSCBS		;BYTE SIZE
	HRRZ C,IMSMPP(I)	;COMPUTE # OF BYTES TO SEND
	SUBI C,(TT)
	JUMPL C,[MOVE D,IMSBFE(I) ;WRAPS AROUND
		 SUB D,Q
		 ADDI C,1(D)	;SO ADD # WDS IN BUFFER
		 JRST .+1]
	IMUL C,T		;FIRST GUESS AT NUMBER OF BITS
	LDB A,[360600,,TT]	;GETS POSITION FIELD OF BYTE PTR
	LDB D,[360600,,IMSMPP(I)]
	SUBM A,D		;CORRECTION TO NUMBER OF BITS
	ADD C,D			;C NOW HAS NUMBER OF SENDABLE BITS IN BUFFER
	SKIPL E			;SKIP IF 32BIT
	 JUMPN A,IMOB5A		;36BIT - JUMP IF NOT 0 (MIDDLE OF WORD)
	CAILE A,4		;32BIT - SKIP IF 4, OR 36BIT 0 - SKIP IF NOT MID-WORD
	 JRST IMOB5B		;32BIT MID-WORD - SEND PART OR REST OF WORD
	CAME TT,IMSBFE(I)	;AT RIGHT OF WORD, IS IT LAST WORD?
	 AOSA TT		;NO, ADVANCE TO NEXT
	  HRR TT,Q		;YES, WRAP AROUND TO FIRST	 
	TLO TT,440000		;SWITCH FROM RIGHT OF WORD TO LEFT OF WORD
	CAMG C,IMSOC7(I)	;SKIP IF TOO BIG FOR ALLOCATE
	 CAILE C,8000.		;FITS IN ALLOCATE, SKIP IF FITS IN IMP MESSAGE
	  JRST IMOB1		;MUST SEND LESS THAN ALL THE BITS IN BUFFER
IMOB0F:	MOVE D,IMSMPP(I)	;SENDING WHOLE BUFFER
	LDB J,[360600,,D]	;ADVANCE IMSMPP TO NEXT WORD BOUNDARY
	ADDI J,-36.(T)		;RH(J) := # BITS TO ADVANCE TO WORD BOUNDARY
	MOVNI J,(J)
	IDIV J,B
	ADDM J,IMSMPC(I)	;SUBTRACT FROM FREE THE BYTES SKIPPED OVER
	MOVNM J,IMPNBO		;BUT RETURN TO FREE AFTER TRANSMISSION
	HLL D,IMSBFE(I)		;NOW ADVANCE IMSMPP TO RIGHT END OF WORD
	MOVEM D,IMSMPP(I)	;AND IMSPIP WILL GET SET EQUAL TO IMSMPP
IMOB0A:	MOVEM D,IMPNPT		;ILDB -> FIRST BYTE TO SEND OUT NEXT TIME
	JUMPLE C,[JRST 4,.]	;SOMEBODY COMPUTED BAD # BITS
	MOVE A,C
	IDIV C,B		;C := # BYTES GETTING SENT
	JUMPN D,[JRST 4,.]	;LOSS, TRYING TO SEND PARTIAL BYTE
	ADDM C,IMPNBO		;# BYTES TO RETURN TO FREE AFTER MSG SENT
	MOVEM A,IMPNBT		;# BITS TO SUBTRACT FROM ALLOCATION THEN
;DROPS THROUGH
;DROPS IN
;NOW SET UP BUFFER HEADER FOR IMP MESSAGE IN IMOLDR
; TT -> FIRST WORD TO SEND
; A NUMBER OF BITS TO SEND
; C NUMBER OF BYTES
; B BYTE SIZE
; T WORD SIZE
; E FLAGS

	LDB H,IMSCFH		;HOST TABLE INDEX
	MOVEI Q,IMOLDR-2	;HACK HACK
	PUSHJ P,STHSTP		;STORE HOST NUMBER, MESSAGE TYPE 0
	LDB Q,IMSCLN		;LINK NUMBER
	DPB Q,[001000,,IMOLDR+1]
	LDB Q,[221000,,IMSOC6(I)] ;GET BUFFER TYPE
	MOVEI D,4
	CAIN Q,377
	 MOVEI D,7
	DPB D,[400400,,IMOLDR+1]	;STORE HANDLING TYPE, DEPENDING ON BUFFER SIZE
	DPB B,[201000,,C]	;STORE SIZE IN SAME WD AS COUNT
	LSH C,8
	MOVEM C,IMOLDR+5	;HOST-HOST HEADER - 00,SIZE,BYTE-COUNT,0000
IFN KAIMP,CONO IMP,IMO32C
IFN DMIMP,CONO FI,FIO32C		;36BIT MODE FOR HEADER, AND NO PIA YET
	DATAO IMP,IMOLDR	;OUTPUT THE FIRST LEADER WORD
	SETZM IMOPNT		;START AT BEGINNING OF IMOLST
	MOVE B,[-5,,IMOLDR]	;SEND REST OF LEADER
	MOVEM B,IMOLST
	MOVEI B,3
	SKIPGE E
	 MOVEI B,2
	MOVEM B,IMOMOD		;SEND DATA IN 32 OR 36 BIT MODE AS APPROPRIATE
	ADDI A,-1(T)		;ROUND UP IF NOT EXACT
	IDIV A,T		;# WDS TO SEND
	MOVEI D,-1(TT)		;FIRST WORD TO SEND MINUS ONE
	ADDI D,(A)		;LAST WORD TO SEND
	CAIG D,@IMSBFE(I)	;SKIP IF WRAP
	 JRST IMOB7
	HRRZ B,IMSBFE(I)	;COMPUTE # TO SEND FIRST TIME
	SUBI B,-1(TT)		;B GETS PLUS NUMBER TO SEND FIRST TIME
	SUBM B,A		;A GETS MINUS NUMBER TO SEND SECOND TIME
	MOVNI C,(B)
	HRLI C,-1(TT)		;C GETS SWAPPED BLKO POINTER FOR FIRST TIME
	MOVE Q,IMSOC6(I)	;POINTER TO BUFFER
IFN KAIMP,[
	MOVEI B,3		;SEND LAST WORD SEPARATELY
	MOVEM B,IMOBK2
	AOJE A,.+3
]	 HRLI A,-1(Q)		;BLKO POINTER FOR SECOND TIME	
	 MOVSM A,IMOBK2
IFN KAIMP,[
	MOVNI A,(A)
	ADDI A,-1(Q)
	HRROM A,IMOBK3		;STORE BLKO POINTER TO LAST WORD
]
	JRST IMOB8		

IMOB7:	MOVSI C,3		;NO WRAP, SO NO SECOND BLKO
	MOVSM C,IMOBK2
IFN KAIMP,[
	SOS D
	HRROM D,IMOBK3		;DO LAST WORD SEPARATELY
	SOJE A,IMOB8		;SPECIAL CASE LAST WORD IS ONLY WORD
]
	MOVNI C,(A)		;MAKE BLKO POINTER
	HRLI C,-1(TT)
IMOB8:	MOVSM C,IMOBK1
	MOVSI TT,400000		;TURN OFF "SEND ME"
	ANDCAM TT,IMSOC4(I)
	HRRZM I,IMPOPI		;SAVE INDEX FOR BLKO RUNOUT
	AOS IMPMSS+0
	MOVEI C,%ISOND		;STATE FOR "END OF DATA"
	JRST IMOB9

;BUFFER CANNOT BE SENT AS 1 MSG.  GRT ALLOC OR 8000 BITS.

IMOB1:	MOVE C,IMSOC7(I)	;ALLOC
	CAILE C,8000.
	 MOVEI C,8000.		;C := MIN(BITS IN BUFFER, ALLOC, MAX IMP MSG SIZE)
	TLNE E,2000		;SKIP IF BYTES EXACTLY FIT IN WORD
	 JRST IMOB3		;MUST SEND MULTI WORDS
	CAMGE C,T		;SKIP IF ALLOC GEQ WDSIZ
	 JRST IMOB2		;MUST SEND PART WORD
	IDIV C,T		;#WDS
	MOVE D,C
	IMUL C,T		;#BITS IN THOSE WDS
IMOB1A:	ADDI D,-1(TT)		;LAST WORD OUTPUT
	CAIG D,@IMSBFE(I)
	 JRST .+3
	  SUBI D,@IMSBFE(I)	;WRAP AROUND
	  ADDI D,-1(Q)
	HLL D,IMSBFE(I)		;PUT IN BYTE PART (RIGHT END OF WORD)
	JRST IMOB0A		;BUILD HEADER AND OUTPUT

;SEND PART OF WORD BECAUSE ALLOC IS TOO SMALL

IMOB2:	MOVE D,TT		;-> FIRST BYTE TO BE SENT
	MOVNI A,-36.(C)		;36-BITS SENT
	DPB A,[360600,,D]	;IS NEXT BYTE TO GO
	JRST IMOB0A

;SEND PARTIAL BUFFER OF BYTES WHICH DO NOT FIT EXACTLY IN WORDS (E.G. 7BIT BYTES)
;MUST SEND A "QUANTUM" WHICH FOR LAZINESS' SAKE IS 36 BYTES

IMOB3:	MOVEI A,36.		;#BITS IN A WORD
	IMUL A,B		;#BITS IN A QUANTUM
	IDIV C,A		;# QUANTA
	JUMPE C,IMOB4		;NOT ENOUGH ALLOC FOR EVEN 1 QUANTUM, SORRY CHARLIE
	MOVE D,C
	IMUL C,A		;#BITS TO SEND
	IMUL D,B		;#WDS TO SEND (36 BYTES TAKE <BYTESIZE> WDS)
	JRST IMOB1A

;NEED MORE ALLOCATE TO SEND A BUFFER FOR THIS ODD-SIZE CONNECTION

IMOB4:	MOVSI T,200000
	ANDCAM T,IMSOC6(I)	;CLEAR "ACTIVE AT PI LEVEL" BIT
	JRST IMPOBA		;MAYBE TRY ANOTHER ONE

;SENDING REST OF PARTIAL WORD (PI PTR NOT AT WORD BOUNDARY)
;A/ BITS LEFT IN WORD

IMOB5A:	SKIPA C,A		;36BIT GETS WHOLE WD
IMOB5B:	 HRREI C,-4(A)		;32BIT GETS 4 LESS
	MOVNI J,-36.(A)		;# BITS SHIFT TO LEFT JUSTIFY
	HRRZ D,TT
	CAIN D,@IMSMPP(I)	;IF WHOLE REST OF BUFFER IS IN THIS WORD
	 JRST [	LDB D,[360600,,IMSMPP(I)]
		SUB A,D		;A := NUMBER OF BITS TO SEND
		MOVE C,(TT)	;ALIGN BITS TO BE SENT IN LEFT OF WORD
		LSH C,(J)
		MOVEM C,(TT)
		MOVE C,A
		JRST IMOB0F ]	;RE-ALIGN POINTERS TO WORD BOUNDARY
	CAMLE C,IMSOC7(I)	;SKIP IF WILL FIT IN ALLOC
	 JRST IMOB6		;MUST SEND BYTES NOT LEFT JUST IN WD, AND MORE TO RIGHT
	MOVE D,(TT)		;GET WORD
	LSH D,(J)		;LEFT JUSTIFY
	MOVEM D,(TT)
	MOVE D,TT
	HLL D,IMSBFE(I)		;ADVANCE PI POINTER TO END OF THIS WORD
	JRST IMOB0A		;BUILD HDR & SEND

;SEND MIDDLE PART OF WORD. BECAUSE OF SMALL ALLOCATES, THE LEFT END OF THE
;   WORD WAS SENT AND ALSO THERE IS NOT ENOUGH ALLOCATE TO SEND THE REST
;   OF THE ONE WORD.  THIS MIGHT NEVER OCCUR EXCEPT FOR 8 BIT BYTES.
;MUST MOVE GOOD BITS TO LEFT END OF WORD, WITHOUT DISTURBING BITS TO THE RIGHT

IMOB6:	MOVE C,IMSOC7(I)	;CAN ONLY SEND ALLOC BITS
	SUB A,C			;POS OF LO BIT TO PICK UP
	DPB A,[360600,,TT]	;POS IN BYTE PTR
	MOVE D,TT		;SAVE ADVANCED PI PNTR
	DPB C,[300600,,TT]	;STORE AS SIZE OF BYTE
	LDB R,TT		;GET BYTE
	MOVNI A,-36.(C)		;POS OF LO BIT TO STORE
	DPB A,[360600,,TT]	;POS IN B PTR
	DPB R,TT		;STORE BYTE AWAY
	JRST IMOB0A		;SEND THE BYTE(S)

OVHMTR UUO	;YET MORE RANDOM UUOS
